missed these with last commit

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1876 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2009-01-15 07:27:06 +00:00
parent ba8c2aa7e4
commit 9dcb4edc97
2 changed files with 199 additions and 218 deletions

View File

@ -1,35 +1,35 @@
// Copyright (C) 2003-2008 Dolphin Project. // Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Include // Include
// ¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯
#include "Thread.h" #include "Thread.h"
#include "Timer.h" #include "Timer.h"
#include "Common.h" #include "Common.h"
#include "Console.h" #include "Console.h"
#include "Core.h" #include "Core.h"
#include "CPUDetect.h" #include "CPUDetect.h"
#include "CoreTiming.h" #include "CoreTiming.h"
#include "Boot/Boot.h" #include "Boot/Boot.h"
#include "PatchEngine.h" #include "PatchEngine.h"
#include "HW/Memmap.h" #include "HW/Memmap.h"
#include "HW/PeripheralInterface.h" #include "HW/PeripheralInterface.h"
#include "HW/GPFifo.h" #include "HW/GPFifo.h"
@ -43,38 +43,35 @@
#include "HW/CommandProcessor.h" #include "HW/CommandProcessor.h"
#include "HW/PixelEngine.h" #include "HW/PixelEngine.h"
#include "HW/SystemTimers.h" #include "HW/SystemTimers.h"
#include "PowerPC/PowerPC.h" #include "PowerPC/PowerPC.h"
#include "Plugins/Plugin_Video.h" #include "PluginManager.h"
#include "Plugins/Plugin_PAD.h"
#include "Plugins/Plugin_DSP.h"
#include "Plugins/Plugin_Wiimote.h"
#include "MemTools.h" #include "MemTools.h"
#include "Host.h" #include "Host.h"
#include "LogManager.h" #include "LogManager.h"
#include "State.h" #include "State.h"
#ifndef _WIN32 #ifndef _WIN32
#define WINAPI #define WINAPI
#endif #endif
//////////////////////////////////////// ////////////////////////////////////////
// The idea behind the recent restructure is to fix various stupid problems. // The idea behind the recent restructure is to fix various stupid problems.
// glXMakeCurrent/ wglMakeCurrent takes a context and makes it current on the current thread. // glXMakeCurrent/ wglMakeCurrent takes a context and makes it current on the current thread.
// So it's fine to init ogl on one thread, and then make it current and start blasting on another. // So it's fine to init ogl on one thread, and then make it current and start blasting on another.
namespace Core namespace Core
{ {
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Declarations and definitions // Declarations and definitions
// ¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯
// Function forwarding // Function forwarding
//void Callback_VideoRequestWindowSize(int _iWidth, int _iHeight, BOOL _bFullscreen); //void Callback_VideoRequestWindowSize(int _iWidth, int _iHeight, BOOL _bFullscreen);
void Callback_VideoLog(const TCHAR* _szMessage, int _bDoBreak); void Callback_VideoLog(const TCHAR* _szMessage, int _bDoBreak);
@ -85,30 +82,30 @@ void Callback_DSPInterrupt();
void Callback_PADLog(const TCHAR* _szMessage); void Callback_PADLog(const TCHAR* _szMessage);
void Callback_WiimoteLog(const TCHAR* _szMessage, int _v); void Callback_WiimoteLog(const TCHAR* _szMessage, int _v);
void Callback_WiimoteInput(u16 _channelID, const void* _pData, u32 _Size); void Callback_WiimoteInput(u16 _channelID, const void* _pData, u32 _Size);
// For keyboard shortcuts. // For keyboard shortcuts.
void Callback_KeyPress(int key, bool shift, bool control); void Callback_KeyPress(int key, bool shift, bool control);
TPeekMessages Callback_PeekMessages = NULL; TPeekMessages Callback_PeekMessages = NULL;
TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL; TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL;
#ifdef _WIN32 #ifdef _WIN32
DWORD WINAPI EmuThread(void *pArg); DWORD WINAPI EmuThread(void *pArg);
#else #else
void *EmuThread(void *pArg); void *EmuThread(void *pArg);
#endif #endif
void Stop(); void Stop();
bool g_bHwInit = false; bool g_bHwInit = false;
bool g_bRealWiimote = false; bool g_bRealWiimote = false;
HWND g_pWindowHandle = NULL; HWND g_pWindowHandle = NULL;
Common::Thread* g_pThread = NULL; Common::Thread* g_pThread = NULL;
SCoreStartupParameter g_CoreStartupParameter; //uck SCoreStartupParameter g_CoreStartupParameter; //uck
Common::Event emuThreadGoing; Common::Event emuThreadGoing;
////////////////////////////////////// //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Display messages and return values // Display messages and return values
// ¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯
@ -117,39 +114,41 @@ bool PanicAlertToVideo(const char* text, bool yes_no)
DisplayMessage(text, 3000); DisplayMessage(text, 3000);
return true; return true;
} }
void DisplayMessage(const std::string &message, int time_in_ms) void DisplayMessage(const std::string &message, int time_in_ms)
{ {
PluginVideo::Video_AddMessage(message.c_str(), time_in_ms); CPluginManager::GetInstance().GetVideo()->Video_AddMessage(message.c_str(),
time_in_ms);
} }
void DisplayMessage(const char *message, int time_in_ms) void DisplayMessage(const char *message, int time_in_ms)
{ {
PluginVideo::Video_AddMessage(message, time_in_ms); CPluginManager::GetInstance().GetVideo()->Video_AddMessage(message,
time_in_ms);
} }
void Callback_DebuggerBreak() void Callback_DebuggerBreak()
{ {
CCPU::EnableStepping(true); CCPU::EnableStepping(true);
} }
const SCoreStartupParameter& GetStartupParameter() const SCoreStartupParameter& GetStartupParameter()
{ {
return g_CoreStartupParameter; return g_CoreStartupParameter;
} }
void* GetWindowHandle() void* GetWindowHandle()
{ {
return g_pWindowHandle; return g_pWindowHandle;
} }
bool GetRealWiimote() bool GetRealWiimote()
{ {
return g_bRealWiimote; return g_bRealWiimote;
} }
///////////////////////////////////// /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// This is called from the GUI thread. See the booting call schedule in BootManager.cpp // This is called from the GUI thread. See the booting call schedule in BootManager.cpp
// ¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯
@ -159,68 +158,56 @@ bool Init(const SCoreStartupParameter _CoreParameter)
PanicAlert("ERROR: Emu Thread already running. Report this bug."); PanicAlert("ERROR: Emu Thread already running. Report this bug.");
return false; return false;
} }
CPluginManager &pManager = CPluginManager::GetInstance();
LogManager::Init(); LogManager::Init();
Host_SetWaitCursor(true); Host_SetWaitCursor(true);
g_CoreStartupParameter = _CoreParameter;
// start the thread again // start the thread again
_dbg_assert_(HLE, g_pThread == NULL); _dbg_assert_(HLE, g_pThread == NULL);
if (!pManager.InitPlugins(_CoreParameter))
return false;
// load plugins g_CoreStartupParameter = _CoreParameter;
if (!PluginDSP::LoadPlugin(g_CoreStartupParameter.m_strDSPPlugin.c_str())) {
return false;
}
if (!PluginPAD::LoadPlugin(g_CoreStartupParameter.m_strPadPlugin.c_str())) {
return false;
}
if (!PluginVideo::LoadPlugin(g_CoreStartupParameter.m_strVideoPlugin.c_str())) {
return false;
}
if (_CoreParameter.bWii && !PluginWiimote::LoadPlugin(g_CoreStartupParameter.m_strWiimotePlugin.c_str())) {
return false;
}
emuThreadGoing.Init(); emuThreadGoing.Init();
// This will execute EmuThread() further down in this file // This will execute EmuThread() further down in this file
g_pThread = new Common::Thread(EmuThread, (void*)&g_CoreStartupParameter); g_pThread = new Common::Thread(EmuThread, (void*)&g_CoreStartupParameter);
emuThreadGoing.Wait(); emuThreadGoing.Wait();
emuThreadGoing.Shutdown(); emuThreadGoing.Shutdown();
// all right ... here we go // all right ... here we go
Host_SetWaitCursor(false); Host_SetWaitCursor(false);
DisplayMessage("CPU: " + cpu_info.Summarize(), 8000); DisplayMessage("CPU: " + cpu_info.Summarize(), 8000);
DisplayMessage(_CoreParameter.m_strFilename, 3000); DisplayMessage(_CoreParameter.m_strFilename, 3000);
//PluginVideo::DllDebugger(NULL); //PluginVideo::DllDebugger(NULL);
return true; return true;
} }
// Called from GUI thread or VI thread // Called from GUI thread or VI thread
void Stop() // - Hammertime! void Stop() // - Hammertime!
{ {
Host_SetWaitCursor(true); Host_SetWaitCursor(true);
if (PowerPC::state == PowerPC::CPU_POWERDOWN) if (PowerPC::state == PowerPC::CPU_POWERDOWN)
return; return;
// stop the CPU // stop the CPU
PowerPC::state = PowerPC::CPU_POWERDOWN; PowerPC::state = PowerPC::CPU_POWERDOWN;
CCPU::StepOpcode(); //kick it if it's waiting CCPU::StepOpcode(); //kick it if it's waiting
// The quit is to get it out of its message loop // The quit is to get it out of its message loop
// Should be moved inside the plugin. // Should be moved inside the plugin.
#ifdef _WIN32 #ifdef _WIN32
PostMessage((HWND)g_pWindowHandle, WM_QUIT, 0, 0); PostMessage((HWND)g_pWindowHandle, WM_QUIT, 0, 0);
#else #else
PluginVideo::Video_Stop(); CPluginManager::GetInstance().GetVideo()->Video_Stop();
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
/* I have to use this to avoid the hangings, it seems harmless and it works so I'm /* I have to use this to avoid the hangings, it seems harmless and it works so I'm
okay with it */ okay with it */
@ -234,21 +221,22 @@ void Stop() // - Hammertime!
LogManager::Shutdown(); LogManager::Shutdown();
Host_SetWaitCursor(false); Host_SetWaitCursor(false);
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Create the CPU thread // Create the CPU thread
// ¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯
THREAD_RETURN CpuThread(void *pArg) THREAD_RETURN CpuThread(void *pArg)
{ {
Common::SetCurrentThreadName("CPU thread"); Common::SetCurrentThreadName("CPU thread");
const SCoreStartupParameter& _CoreParameter = g_CoreStartupParameter; const SCoreStartupParameter& _CoreParameter = g_CoreStartupParameter;
if (!g_CoreStartupParameter.bUseDualCore) if (!g_CoreStartupParameter.bUseDualCore)
{ {
PluginVideo::Video_Prepare(); //wglMakeCurrent //wglMakeCurrent
CPluginManager::GetInstance().GetVideo()->Video_Prepare();
} }
if (_CoreParameter.bRunCompareServer) if (_CoreParameter.bRunCompareServer)
{ {
CPUCompare::StartServer(); CPUCompare::StartServer();
@ -259,10 +247,10 @@ THREAD_RETURN CpuThread(void *pArg)
PanicAlert("Compare Debug : Press OK when ready."); PanicAlert("Compare Debug : Press OK when ready.");
CPUCompare::ConnectAsClient(); CPUCompare::ConnectAsClient();
} }
if (_CoreParameter.bLockThreads) if (_CoreParameter.bLockThreads)
Common::Thread::SetCurrentThreadAffinity(1); //Force to first core Common::Thread::SetCurrentThreadAffinity(1); //Force to first core
if (_CoreParameter.bUseFastMem) if (_CoreParameter.bUseFastMem)
{ {
#ifdef _M_X64 #ifdef _M_X64
@ -272,9 +260,9 @@ THREAD_RETURN CpuThread(void *pArg)
PanicAlert("32-bit platforms do not support fastmem yet. Report this bug."); PanicAlert("32-bit platforms do not support fastmem yet. Report this bug.");
#endif #endif
} }
CCPU::Run(); CCPU::Run();
if (_CoreParameter.bRunCompareServer || _CoreParameter.bRunCompareClient) if (_CoreParameter.bRunCompareServer || _CoreParameter.bRunCompareClient)
{ {
CPUCompare::Stop(); CPUCompare::Stop();
@ -282,8 +270,8 @@ THREAD_RETURN CpuThread(void *pArg)
return 0; return 0;
} }
////////////////////////////////////////// //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Initalize plugins and create emulation thread // Initalize plugins and create emulation thread
// ¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯
@ -292,18 +280,18 @@ THREAD_RETURN CpuThread(void *pArg)
THREAD_RETURN EmuThread(void *pArg) THREAD_RETURN EmuThread(void *pArg)
{ {
Common::SetCurrentThreadName("Emuthread - starting"); Common::SetCurrentThreadName("Emuthread - starting");
const SCoreStartupParameter& _CoreParameter = *(SCoreStartupParameter*)pArg; const SCoreStartupParameter _CoreParameter = *(SCoreStartupParameter*)pArg;
CPluginManager &pm = CPluginManager::GetInstance();
if (_CoreParameter.bLockThreads) if (_CoreParameter.bLockThreads)
Common::Thread::SetCurrentThreadAffinity(2); // Force to second core Common::Thread::SetCurrentThreadAffinity(2); // Force to second core
LOG(OSREPORT, "Starting core = %s mode", _CoreParameter.bWii ? "Wii" : "Gamecube"); LOG(OSREPORT, "Starting core = %s mode", _CoreParameter.bWii ? "Wii" : "Gamecube");
LOG(OSREPORT, "Dualcore = %s", _CoreParameter.bUseDualCore ? "Yes" : "No"); LOG(OSREPORT, "Dualcore = %s", _CoreParameter.bUseDualCore ? "Yes" : "No");
HW::Init(); HW::Init();
emuThreadGoing.Set(); emuThreadGoing.Set();
// Load the VideoPlugin // Load the VideoPlugin
SVideoInitialize VideoInitialize; SVideoInitialize VideoInitialize;
VideoInitialize.pGetMemoryPointer = Memory::GetPointer; VideoInitialize.pGetMemoryPointer = Memory::GetPointer;
@ -323,13 +311,13 @@ THREAD_RETURN EmuThread(void *pArg)
VideoInitialize.pMemoryBase = Memory::base; VideoInitialize.pMemoryBase = Memory::base;
VideoInitialize.pKeyPress = Callback_KeyPress; VideoInitialize.pKeyPress = Callback_KeyPress;
VideoInitialize.bWii = _CoreParameter.bWii; VideoInitialize.bWii = _CoreParameter.bWii;
PluginVideo::Video_Initialize(&VideoInitialize); // Call the dll pm.GetVideo()->Initialize(&VideoInitialize); // Call the dll
// Under linux, this is an X11 Display, not an HWND! // Under linux, this is an X11 Display, not an HWND!
g_pWindowHandle = (HWND)VideoInitialize.pWindowHandle; g_pWindowHandle = (HWND)VideoInitialize.pWindowHandle;
Callback_PeekMessages = VideoInitialize.pPeekMessages; Callback_PeekMessages = VideoInitialize.pPeekMessages;
g_pUpdateFPSDisplay = VideoInitialize.pUpdateFPSDisplay; g_pUpdateFPSDisplay = VideoInitialize.pUpdateFPSDisplay;
// Load and init DSPPlugin // Load and init DSPPlugin
DSPInitialize dspInit; DSPInitialize dspInit;
dspInit.hWnd = g_pWindowHandle; dspInit.hWnd = g_pWindowHandle;
@ -341,14 +329,14 @@ THREAD_RETURN EmuThread(void *pArg)
dspInit.pDebuggerBreak = Callback_DebuggerBreak; dspInit.pDebuggerBreak = Callback_DebuggerBreak;
dspInit.pGenerateDSPInterrupt = Callback_DSPInterrupt; dspInit.pGenerateDSPInterrupt = Callback_DSPInterrupt;
dspInit.pGetAudioStreaming = AudioInterface::Callback_GetStreaming; dspInit.pGetAudioStreaming = AudioInterface::Callback_GetStreaming;
PluginDSP::DSP_Initialize(dspInit); pm.GetDSP()->Initialize((void *)&dspInit);
// Load and Init PadPlugin // Load and Init PadPlugin
SPADInitialize PADInitialize; SPADInitialize PADInitialize;
PADInitialize.hWnd = g_pWindowHandle; PADInitialize.hWnd = g_pWindowHandle;
PADInitialize.pLog = Callback_PADLog; PADInitialize.pLog = Callback_PADLog;
PluginPAD::PAD_Initialize(PADInitialize); pm.GetPAD(0)->Initialize((void *)&PADInitialize);
// Load and Init WiimotePlugin - only if we are booting in wii mode // Load and Init WiimotePlugin - only if we are booting in wii mode
if (_CoreParameter.bWii) { if (_CoreParameter.bWii) {
SWiimoteInitialize WiimoteInitialize; SWiimoteInitialize WiimoteInitialize;
@ -356,42 +344,42 @@ THREAD_RETURN EmuThread(void *pArg)
WiimoteInitialize.pLog = Callback_WiimoteLog; WiimoteInitialize.pLog = Callback_WiimoteLog;
WiimoteInitialize.pWiimoteInput = Callback_WiimoteInput; WiimoteInitialize.pWiimoteInput = Callback_WiimoteInput;
// Wait for Wiiuse to find the number of connected Wiimotes // Wait for Wiiuse to find the number of connected Wiimotes
g_bRealWiimote = PluginWiimote::Wiimote_Initialize(WiimoteInitialize); pm.GetWiimote(0)->Initialize((void *)&WiimoteInitialize);
} }
// The hardware is initialized. // The hardware is initialized.
g_bHwInit = true; g_bHwInit = true;
// Load GCM/DOL/ELF whatever ... we boot with the interpreter core // Load GCM/DOL/ELF whatever ... we boot with the interpreter core
PowerPC::SetMode(PowerPC::MODE_INTERPRETER); PowerPC::SetMode(PowerPC::MODE_INTERPRETER);
CBoot::BootUp(_CoreParameter); CBoot::BootUp(_CoreParameter);
if( g_pUpdateFPSDisplay != NULL ) if( g_pUpdateFPSDisplay != NULL )
g_pUpdateFPSDisplay("Loading..."); g_pUpdateFPSDisplay("Loading...");
// 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)) if (_CoreParameter.bUseJIT && (!_CoreParameter.bRunCompareServer || _CoreParameter.bRunCompareClient))
PowerPC::SetMode(PowerPC::MODE_JIT); PowerPC::SetMode(PowerPC::MODE_JIT);
else else
PowerPC::SetMode(PowerPC::MODE_INTERPRETER); 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_UpdateDisasmDialog();
Host_UpdateMainFrame(); Host_UpdateMainFrame();
//This thread, after creating the EmuWindow, spawns a CPU thread, //This thread, after creating the EmuWindow, spawns a CPU thread,
//then takes over and becomes the graphics thread //then takes over and becomes the graphics thread
//In single core mode, the CPU thread does the graphics. In fact, the //In single core mode, the CPU thread does the graphics. In fact, the
//CPU thread should in this case also create the emuwindow... //CPU thread should in this case also create the emuwindow...
// Spawn the CPU thread // Spawn the CPU thread
Common::Thread *cpuThread = NULL; Common::Thread *cpuThread = NULL;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// ENTER THE VIDEO THREAD LOOP // ENTER THE VIDEO THREAD LOOP
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
if (!Core::GetStartupParameter().bUseDualCore) if (!Core::GetStartupParameter().bUseDualCore)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -414,17 +402,17 @@ THREAD_RETURN EmuThread(void *pArg)
else else
{ {
cpuThread = new Common::Thread(CpuThread, pArg); cpuThread = new Common::Thread(CpuThread, pArg);
PluginVideo::Video_Prepare(); //wglMakeCurrent pm.GetVideo()->Video_Prepare(); //wglMakeCurrent
Common::SetCurrentThreadName("Video thread"); Common::SetCurrentThreadName("Video thread");
PluginVideo::Video_EnterLoop(); pm.GetVideo()->Video_EnterLoop();
} }
// Wait for CPU thread to exit - it should have been signaled to do so by now // Wait for CPU thread to exit - it should have been signaled to do so by now
if (cpuThread) if (cpuThread)
cpuThread->WaitForDeath(); cpuThread->WaitForDeath();
if (g_pUpdateFPSDisplay != NULL) if (g_pUpdateFPSDisplay != NULL)
g_pUpdateFPSDisplay("Stopping..."); g_pUpdateFPSDisplay("Stopping...");
if (cpuThread) if (cpuThread)
{ {
delete cpuThread; // This joins the cpu thread. delete cpuThread; // This joins the cpu thread.
@ -432,21 +420,11 @@ THREAD_RETURN EmuThread(void *pArg)
cpuThread = NULL; cpuThread = NULL;
} }
g_bHwInit = false; g_bHwInit = false;
PluginPAD::PAD_Shutdown(); pm.ShutdownPlugins();
PluginPAD::UnloadPlugin();
if (_CoreParameter.bWii)
{
PluginWiimote::Wiimote_Shutdown();
PluginWiimote::UnloadPlugin();
}
PluginDSP::DSP_Shutdown();
PluginDSP::UnloadPlugin();
PluginVideo::Video_Shutdown();
PluginVideo::UnloadPlugin();
HW::Shutdown(); HW::Shutdown();
LOG(MASTER_LOG, "EmuThread exited"); LOG(MASTER_LOG, "EmuThread exited");
// The CPU should return when a game is stopped and cleanup should be done here, // The CPU should return when a game is stopped and cleanup should be done here,
// so we can restart the plugins (or load new ones) for the next game. // so we can restart the plugins (or load new ones) for the next game.
@ -454,8 +432,8 @@ THREAD_RETURN EmuThread(void *pArg)
Host_UpdateMainFrame(); Host_UpdateMainFrame();
return 0; return 0;
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Set or get the running state // Set or get the running state
// ¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯
@ -466,22 +444,22 @@ bool SetState(EState _State)
case CORE_UNINITIALIZED: case CORE_UNINITIALIZED:
Stop(); Stop();
break; break;
case CORE_PAUSE: case CORE_PAUSE:
CCPU::EnableStepping(true); CCPU::EnableStepping(true);
break; break;
case CORE_RUN: case CORE_RUN:
CCPU::EnableStepping(false); CCPU::EnableStepping(false);
break; break;
default: default:
return false; return false;
} }
return true; return true;
} }
EState GetState() EState GetState()
{ {
if (g_bHwInit) if (g_bHwInit)
@ -494,38 +472,41 @@ EState GetState()
return CORE_UNINITIALIZED; return CORE_UNINITIALIZED;
} }
/////////////////////////////////////// ///////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Save or recreate the emulation state // Save or recreate the emulation state
// ¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯
void SaveState() { void SaveState() {
State_Save(0); State_Save(0);
} }
void LoadState() { void LoadState() {
State_Load(0); State_Load(0);
} }
/////////////////////////////////////// ///////////////////////////////////////
bool MakeScreenshot(const std::string &filename) bool MakeScreenshot(const std::string &filename)
{ {
bool bResult = false; bool bResult = false;
if (PluginVideo::IsLoaded()) CPluginManager &pManager = CPluginManager::GetInstance();
if (pManager.GetVideo()->IsValid())
{ {
TCHAR szTmpFilename[MAX_PATH]; TCHAR szTmpFilename[MAX_PATH];
strcpy(szTmpFilename, filename.c_str()); strcpy(szTmpFilename, filename.c_str());
bResult = PluginVideo::Video_Screenshot(szTmpFilename) ? true : false; bResult = pManager.GetVideo()->Video_Screenshot(szTmpFilename) ? true : false;
} }
return bResult; return bResult;
} }
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
// --- Callbacks for plugins / engine --- // --- Callbacks for plugins / engine ---
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
// Callback_VideoLog // Callback_VideoLog
// WARNING - THIS IS EXECUTED FROM VIDEO THREAD // WARNING - THIS IS EXECUTED FROM VIDEO THREAD
@ -533,7 +514,7 @@ void Callback_VideoLog(const TCHAR *_szMessage, int _bDoBreak)
{ {
LOG(VIDEO, _szMessage); LOG(VIDEO, _szMessage);
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
// Callback_VideoCopiedToXFB // Callback_VideoCopiedToXFB
// WARNING - THIS IS EXECUTED FROM VIDEO THREAD // WARNING - THIS IS EXECUTED FROM VIDEO THREAD
@ -546,18 +527,18 @@ void Callback_VideoCopiedToXFB()
static u64 ticks = 0; static u64 ticks = 0;
static u64 idleTicks = 0; static u64 idleTicks = 0;
frames++; frames++;
if (Timer.GetTimeDifference() >= 1000) if (Timer.GetTimeDifference() >= 1000)
{ {
u64 newTicks = CoreTiming::GetTicks(); u64 newTicks = CoreTiming::GetTicks();
u64 newIdleTicks = CoreTiming::GetIdleTicks(); u64 newIdleTicks = CoreTiming::GetIdleTicks();
s64 diff = (newTicks - ticks)/1000000; s64 diff = (newTicks - ticks)/1000000;
s64 idleDiff = (newIdleTicks - idleTicks)/1000000; s64 idleDiff = (newIdleTicks - idleTicks)/1000000;
ticks = newTicks; ticks = newTicks;
idleTicks = newIdleTicks; idleTicks = newIdleTicks;
float t = (float)(Timer.GetTimeDifference()) / 1000.f; float t = (float)(Timer.GetTimeDifference()) / 1000.f;
char temp[256]; char temp[256];
sprintf(temp, "FPS:%8.2f - Core: %s | %s - Speed: %i MHz [Real: %i + IdleSkip: %i] / %i MHz", sprintf(temp, "FPS:%8.2f - Core: %s | %s - Speed: %i MHz [Real: %i + IdleSkip: %i] / %i MHz",
@ -568,20 +549,20 @@ void Callback_VideoCopiedToXFB()
(int)(diff-idleDiff), (int)(diff-idleDiff),
(int)(idleDiff), (int)(idleDiff),
SystemTimers::GetTicksPerSecond()/1000000); SystemTimers::GetTicksPerSecond()/1000000);
if (g_pUpdateFPSDisplay != NULL) if (g_pUpdateFPSDisplay != NULL)
g_pUpdateFPSDisplay(temp); g_pUpdateFPSDisplay(temp);
Host_UpdateStatusBar(temp); Host_UpdateStatusBar(temp);
frames = 0; frames = 0;
Timer.Update(); Timer.Update();
} }
PatchEngine::ApplyFramePatches(); PatchEngine::ApplyFramePatches();
PatchEngine::ApplyARPatches(); PatchEngine::ApplyARPatches();
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
// Callback_DSPLog // Callback_DSPLog
// WARNING - THIS MAY EXECUTED FROM DSP THREAD // WARNING - THIS MAY EXECUTED FROM DSP THREAD
@ -589,7 +570,7 @@ void Callback_DSPLog(const TCHAR* _szMessage, int _v)
{ {
LOGV(AUDIO, _v, _szMessage); LOGV(AUDIO, _v, _szMessage);
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
// Callback_DSPInterrupt // Callback_DSPInterrupt
// WARNING - THIS MAY EXECUTED FROM DSP THREAD // WARNING - THIS MAY EXECUTED FROM DSP THREAD
@ -597,7 +578,7 @@ void Callback_DSPInterrupt()
{ {
DSP::GenerateDSPInterruptFromPlugin(DSP::INT_DSP); DSP::GenerateDSPInterruptFromPlugin(DSP::INT_DSP);
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
// Callback_PADLog // Callback_PADLog
// //
@ -605,7 +586,7 @@ void Callback_PADLog(const TCHAR* _szMessage)
{ {
LOG(SERIALINTERFACE, _szMessage); LOG(SERIALINTERFACE, _szMessage);
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
// Callback_ISOName: Let the DSP plugin get the game name // Callback_ISOName: Let the DSP plugin get the game name
// //
@ -617,7 +598,7 @@ const char *Callback_ISOName(void)
else else
return (const char *)""; return (const char *)"";
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
// Called from ANY thread! // Called from ANY thread!
void Callback_KeyPress(int key, bool shift, bool control) void Callback_KeyPress(int key, bool shift, bool control)
@ -633,7 +614,7 @@ void Callback_KeyPress(int key, bool shift, bool control)
} }
} }
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
// Callback_WiimoteLog // Callback_WiimoteLog
// //
@ -641,5 +622,5 @@ void Callback_WiimoteLog(const TCHAR* _szMessage, int _v)
{ {
LOGV(WII_IPC_WIIMOTE, _v, _szMessage); LOGV(WII_IPC_WIIMOTE, _v, _szMessage);
} }
} // end of namespace Core } // end of namespace Core

View File

@ -23,10 +23,10 @@
// - ZWW as Crazy Taxi: PEfinish (GXSetDrawDone) // - ZWW as Crazy Taxi: PEfinish (GXSetDrawDone)
// - SMS: BP, PEToken, PEfinish // - SMS: BP, PEToken, PEfinish
// - ZTP: seems to use PEfinish only // - ZTP: seems to use PEfinish only
// - Animal Crossing: PEfinish at start but there's a bug... // - Animal Crossing: PEfinish at start but there's a bug...
// There's tons of HiWmk/LoWmk ping pong -> Another sync fashion? // There's tons of HiWmk/LoWmk ping pong -> Another sync fashion?
// - Super Monkey Ball Adventures: PEToken. Oddity: read&check-PEToken-value-loop stays // - Super Monkey Ball Adventures: PEToken. Oddity: read&check-PEToken-value-loop stays
// in its JITed block (never fall in Advance() until the game-watchdog's stuff). // in its JITed block (never fall in Advance() until the game-watchdog's stuff).
// That's why we can't let perform the AdvanceCallBack as usual. // That's why we can't let perform the AdvanceCallBack as usual.
// The PEToken is volatile now and in the fifo struct. // The PEToken is volatile now and in the fifo struct.
// - Super Monkey Ball: PEFinish. This game has the lamest way to deal with fifo sync for our MT's stuff. // - Super Monkey Ball: PEFinish. This game has the lamest way to deal with fifo sync for our MT's stuff.
@ -34,8 +34,8 @@
// *What I guess (thx to asynchronous DualCore mode): // *What I guess (thx to asynchronous DualCore mode):
// PPC have a frame-finish watchdog. Handled by system timming stuff like the decrementer. // PPC have a frame-finish watchdog. Handled by system timming stuff like the decrementer.
// (DualCore mode): I have observed, after ZTP logos, a fifo-recovery start when DECREMENTER_EXCEPTION is throwned. // (DualCore mode): I have observed, after ZTP logos, a fifo-recovery start when DECREMENTER_EXCEPTION is throwned.
// The frame setting (by GP) took too much time and didn't finish properly due to this watchdog. // The frame setting (by GP) took too much time and didn't finish properly due to this watchdog.
// Faster GX plugins required, indeed :p // Faster GX plugins required, indeed :p
// * BPs are needed for some game GP/CPU sync. // * BPs are needed for some game GP/CPU sync.
@ -68,9 +68,9 @@
// * Cleanup of messy now unnecessary safety code in jit // * Cleanup of messy now unnecessary safety code in jit
#include "Common.h" #include "Common.h"
#include "../Plugins/Plugin_Video.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
#include "../CoreTiming.h" #include "../CoreTiming.h"
#include "../PluginManager.h"
#include "MathUtil.h" #include "MathUtil.h"
#include "Thread.h" #include "Thread.h"
@ -90,7 +90,7 @@ namespace CommandProcessor
// Fifo Status Register // Fifo Status Register
union UCPStatusReg union UCPStatusReg
{ {
struct struct
{ {
unsigned OverflowHiWatermark : 1; unsigned OverflowHiWatermark : 1;
unsigned UnderflowLoWatermark : 1; unsigned UnderflowLoWatermark : 1;
@ -107,7 +107,7 @@ union UCPStatusReg
// Fifo Control Register // Fifo Control Register
union UCPCtrlReg union UCPCtrlReg
{ {
struct struct
{ {
unsigned GPReadEnable : 1; unsigned GPReadEnable : 1;
unsigned CPIntEnable : 1; unsigned CPIntEnable : 1;
@ -125,7 +125,7 @@ union UCPCtrlReg
// Fifo Control Register // Fifo Control Register
union UCPClearReg union UCPClearReg
{ {
struct struct
{ {
unsigned ClearFifoOverflow : 1; unsigned ClearFifoOverflow : 1;
unsigned ClearFifoUnderflow : 1; unsigned ClearFifoUnderflow : 1;
@ -191,7 +191,7 @@ void WaitForFrameFinish()
{ {
while ((fake_GPWatchdogLastToken == fifo.Fake_GPWDToken) && fifo.bFF_GPReadEnable && (fifo.CPReadWriteDistance > 0) && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint)) while ((fake_GPWatchdogLastToken == fifo.Fake_GPWDToken) && fifo.bFF_GPReadEnable && (fifo.CPReadWriteDistance > 0) && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint))
Common::SleepCurrentThread(1); Common::SleepCurrentThread(1);
fake_GPWatchdogLastToken = fifo.Fake_GPWDToken; fake_GPWatchdogLastToken = fifo.Fake_GPWDToken;
} }
@ -275,36 +275,36 @@ void Read16(u16& _rReturnValue, const u32 _Address)
case FIFO_LO_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPLoWatermark); return; case FIFO_LO_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPLoWatermark); return;
// TODO: cases cleanup // TODO: cases cleanup
case FIFO_RW_DISTANCE_LO: case FIFO_RW_DISTANCE_LO:
//_rReturnValue = ReadLow (fifo.CPReadWriteDistance); //_rReturnValue = ReadLow (fifo.CPReadWriteDistance);
// hack: CPU will always believe fifo is empty and on idle // hack: CPU will always believe fifo is empty and on idle
_rReturnValue = 0; _rReturnValue = 0;
LOG(COMMANDPROCESSOR,"read FIFO_RW_DISTANCE_LO : %04x", _rReturnValue); LOG(COMMANDPROCESSOR,"read FIFO_RW_DISTANCE_LO : %04x", _rReturnValue);
return; return;
case FIFO_RW_DISTANCE_HI: case FIFO_RW_DISTANCE_HI:
//_rReturnValue = ReadHigh(fifo.CPReadWriteDistance); //_rReturnValue = ReadHigh(fifo.CPReadWriteDistance);
// hack: CPU will always believe fifo is empty and on idle // hack: CPU will always believe fifo is empty and on idle
_rReturnValue = 0; _rReturnValue = 0;
LOG(COMMANDPROCESSOR,"read FIFO_RW_DISTANCE_HI : %04x", _rReturnValue); LOG(COMMANDPROCESSOR,"read FIFO_RW_DISTANCE_HI : %04x", _rReturnValue);
return; return;
case FIFO_WRITE_POINTER_LO: case FIFO_WRITE_POINTER_LO:
_rReturnValue = ReadLow (fifo.CPWritePointer); _rReturnValue = ReadLow (fifo.CPWritePointer);
LOG(COMMANDPROCESSOR,"read FIFO_WRITE_POINTER_LO : %04x", _rReturnValue); LOG(COMMANDPROCESSOR,"read FIFO_WRITE_POINTER_LO : %04x", _rReturnValue);
return; return;
case FIFO_WRITE_POINTER_HI: case FIFO_WRITE_POINTER_HI:
_rReturnValue = ReadHigh(fifo.CPWritePointer); _rReturnValue = ReadHigh(fifo.CPWritePointer);
LOG(COMMANDPROCESSOR,"read FIFO_WRITE_POINTER_HI : %04x", _rReturnValue); LOG(COMMANDPROCESSOR,"read FIFO_WRITE_POINTER_HI : %04x", _rReturnValue);
return; return;
case FIFO_READ_POINTER_LO: case FIFO_READ_POINTER_LO:
//_rReturnValue = ReadLow (fifo.CPReadPointer); //_rReturnValue = ReadLow (fifo.CPReadPointer);
// hack: CPU will always believe fifo is empty and on idle // hack: CPU will always believe fifo is empty and on idle
_rReturnValue = ReadLow (fifo.CPWritePointer); _rReturnValue = ReadLow (fifo.CPWritePointer);
LOG(COMMANDPROCESSOR,"read FIFO_READ_POINTER_LO : %04x", _rReturnValue); LOG(COMMANDPROCESSOR,"read FIFO_READ_POINTER_LO : %04x", _rReturnValue);
return; return;
case FIFO_READ_POINTER_HI: case FIFO_READ_POINTER_HI:
//_rReturnValue = ReadHigh(fifo.CPReadPointer); //_rReturnValue = ReadHigh(fifo.CPReadPointer);
// hack: CPU will always believe fifo is empty and on idle // hack: CPU will always believe fifo is empty and on idle
_rReturnValue = ReadHigh(fifo.CPWritePointer); _rReturnValue = ReadHigh(fifo.CPWritePointer);
LOG(COMMANDPROCESSOR,"read FIFO_READ_POINTER_HI : %04x", _rReturnValue); LOG(COMMANDPROCESSOR,"read FIFO_READ_POINTER_HI : %04x", _rReturnValue);
return; return;
case FIFO_BP_LO: _rReturnValue = ReadLow (fifo.CPBreakpoint); return; case FIFO_BP_LO: _rReturnValue = ReadLow (fifo.CPBreakpoint); return;
@ -421,7 +421,7 @@ void Write16(const u16 _Value, const u32 _Address)
// funny hack: eg in MP1 if we disable the clear breakpoint ability by commenting this block // funny hack: eg in MP1 if we disable the clear breakpoint ability by commenting this block
// the game is of course faster but looks stable too. // the game is of course faster but looks stable too.
// Well, the hack is more stable than the "proper" way actualy :p ... it breaks MP2 when ship lands // Well, the hack is more stable than the "proper" way actualy :p ... it breaks MP2 when ship lands
// So I let the hack for now. // So I let the hack for now.
// TODO (mb2): fix this! // TODO (mb2): fix this!
// BP interrupt is cleared here // BP interrupt is cleared here
@ -464,75 +464,75 @@ void Write16(const u16 _Value, const u32 _Address)
break; break;
// Fifo Registers // Fifo Registers
case FIFO_TOKEN_REGISTER: case FIFO_TOKEN_REGISTER:
m_tokenReg = _Value; m_tokenReg = _Value;
LOG(COMMANDPROCESSOR,"\t write to FIFO_TOKEN_REGISTER : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_TOKEN_REGISTER : %04x", _Value);
break; break;
case FIFO_BASE_LO: case FIFO_BASE_LO:
WriteLow ((u32 &)fifo.CPBase, _Value); WriteLow ((u32 &)fifo.CPBase, _Value);
fifo.CPBase &= 0xFFFFFFE0; fifo.CPBase &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO : %04x", _Value);
break; break;
case FIFO_BASE_HI: case FIFO_BASE_HI:
WriteHigh((u32 &)fifo.CPBase, _Value); WriteHigh((u32 &)fifo.CPBase, _Value);
fifo.CPBase &= 0xFFFFFFE0; fifo.CPBase &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI : %04x", _Value);
break; break;
case FIFO_END_LO: case FIFO_END_LO:
WriteLow ((u32 &)fifo.CPEnd, _Value); WriteLow ((u32 &)fifo.CPEnd, _Value);
fifo.CPEnd &= 0xFFFFFFE0; fifo.CPEnd &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO : %04x", _Value);
break; break;
case FIFO_END_HI: case FIFO_END_HI:
WriteHigh((u32 &)fifo.CPEnd, _Value); WriteHigh((u32 &)fifo.CPEnd, _Value);
fifo.CPEnd &= 0xFFFFFFE0; fifo.CPEnd &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_END_HI : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_END_HI : %04x", _Value);
break; break;
// Hm. Should we really & these with FFFFFFE0? // Hm. Should we really & these with FFFFFFE0?
// (mb2): never seen 32B not aligned values for those following regs. // (mb2): never seen 32B not aligned values for those following regs.
// fifo.CPEnd is the only value that could be not 32B aligned so far. // fifo.CPEnd is the only value that could be not 32B aligned so far.
case FIFO_WRITE_POINTER_LO: case FIFO_WRITE_POINTER_LO:
WriteLow ((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0; WriteLow ((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO : %04x", _Value);
break; break;
case FIFO_WRITE_POINTER_HI: case FIFO_WRITE_POINTER_HI:
WriteHigh((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0; WriteHigh((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI : %04x", _Value);
break; break;
case FIFO_READ_POINTER_LO: case FIFO_READ_POINTER_LO:
WriteLow ((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0; WriteLow ((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO : %04x", _Value);
break; break;
case FIFO_READ_POINTER_HI: case FIFO_READ_POINTER_HI:
WriteHigh((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0; WriteHigh((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI : %04x", _Value);
break; break;
case FIFO_HI_WATERMARK_LO: case FIFO_HI_WATERMARK_LO:
WriteLow ((u32 &)fifo.CPHiWatermark, _Value); WriteLow ((u32 &)fifo.CPHiWatermark, _Value);
LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_LO : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_LO : %04x", _Value);
break; break;
case FIFO_HI_WATERMARK_HI: case FIFO_HI_WATERMARK_HI:
WriteHigh((u32 &)fifo.CPHiWatermark, _Value); WriteHigh((u32 &)fifo.CPHiWatermark, _Value);
LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_HI : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_HI : %04x", _Value);
break; break;
case FIFO_LO_WATERMARK_LO: case FIFO_LO_WATERMARK_LO:
WriteLow ((u32 &)fifo.CPLoWatermark, _Value); WriteLow ((u32 &)fifo.CPLoWatermark, _Value);
LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_LO : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_LO : %04x", _Value);
break; break;
case FIFO_LO_WATERMARK_HI: case FIFO_LO_WATERMARK_HI:
WriteHigh((u32 &)fifo.CPLoWatermark, _Value); WriteHigh((u32 &)fifo.CPLoWatermark, _Value);
LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_HI : %04x", _Value); LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_HI : %04x", _Value);
break; break;
case FIFO_BP_LO: case FIFO_BP_LO:
WriteLow ((u32 &)fifo.CPBreakpoint, _Value); WriteLow ((u32 &)fifo.CPBreakpoint, _Value);
LOG(COMMANDPROCESSOR,"write to FIFO_BP_LO : %04x", _Value); LOG(COMMANDPROCESSOR,"write to FIFO_BP_LO : %04x", _Value);
break; break;
case FIFO_BP_HI: case FIFO_BP_HI:
WriteHigh((u32 &)fifo.CPBreakpoint, _Value); WriteHigh((u32 &)fifo.CPBreakpoint, _Value);
LOG(COMMANDPROCESSOR,"write to FIFO_BP_HI : %04x", _Value); LOG(COMMANDPROCESSOR,"write to FIFO_BP_HI : %04x", _Value);
break; break;
@ -541,10 +541,10 @@ void Write16(const u16 _Value, const u32 _Address)
// When we fall here CPReadWriteDistance should be always null and the game should always want to overwrite it by 0. // When we fall here CPReadWriteDistance should be always null and the game should always want to overwrite it by 0.
// So, we can skip it. // So, we can skip it.
case FIFO_RW_DISTANCE_HI: case FIFO_RW_DISTANCE_HI:
//WriteHigh((u32 &)fifo.CPReadWriteDistance, _Value); //WriteHigh((u32 &)fifo.CPReadWriteDistance, _Value);
LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_HI : %04x", _Value); LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
break; break;
case FIFO_RW_DISTANCE_LO: case FIFO_RW_DISTANCE_LO:
//WriteLow((u32 &)fifo.CPReadWriteDistance, _Value); //WriteLow((u32 &)fifo.CPReadWriteDistance, _Value);
LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_LO : %04x", _Value); LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_LO : %04x", _Value);
break; break;
@ -576,7 +576,7 @@ void STACKALIGN GatherPipeBursted()
{ {
// update the fifo-pointer // update the fifo-pointer
fifo.CPWritePointer += GPFifo::GATHER_PIPE_SIZE; fifo.CPWritePointer += GPFifo::GATHER_PIPE_SIZE;
if (fifo.CPWritePointer >= fifo.CPEnd) if (fifo.CPWritePointer >= fifo.CPEnd)
fifo.CPWritePointer = fifo.CPBase; fifo.CPWritePointer = fifo.CPBase;
Common::SyncInterlockedExchangeAdd((LONG*)&fifo.CPReadWriteDistance, GPFifo::GATHER_PIPE_SIZE); Common::SyncInterlockedExchangeAdd((LONG*)&fifo.CPReadWriteDistance, GPFifo::GATHER_PIPE_SIZE);
@ -594,7 +594,7 @@ void STACKALIGN GatherPipeBursted()
// - @ game start -> watermark init: Overflow enabled, Underflow disabled // - @ game start -> watermark init: Overflow enabled, Underflow disabled
// - if (OV is raised) // - if (OV is raised)
// - CPU stop to write to fifo // - CPU stop to write to fifo
// - enable Underflow interrupt (this only happens if OV is raised) // - enable Underflow interrupt (this only happens if OV is raised)
// - do other things // - do other things
// - if (Underflow is raised (implicite: AND if an OV has been raised)) // - if (Underflow is raised (implicite: AND if an OV has been raised))
// - CPU can write to fifo // - CPU can write to fifo
@ -618,7 +618,7 @@ void STACKALIGN GatherPipeBursted()
else else
{ {
fifo.CPWritePointer += GPFifo::GATHER_PIPE_SIZE; fifo.CPWritePointer += GPFifo::GATHER_PIPE_SIZE;
if (fifo.CPWritePointer >= fifo.CPEnd) if (fifo.CPWritePointer >= fifo.CPEnd)
fifo.CPWritePointer = fifo.CPBase; fifo.CPWritePointer = fifo.CPBase;
// check if we are in sync // check if we are in sync
_assert_msg_(COMMANDPROCESSOR, fifo.CPWritePointer == CPeripheralInterface::Fifo_CPUWritePointer, "FIFOs linked but out of sync"); _assert_msg_(COMMANDPROCESSOR, fifo.CPWritePointer == CPeripheralInterface::Fifo_CPUWritePointer, "FIFOs linked but out of sync");
@ -646,7 +646,7 @@ void CatchUpGPU()
{ {
//_assert_msg_(GEKKO,0,"BP: %08x",fifo.CPBreakpoint); //_assert_msg_(GEKKO,0,"BP: %08x",fifo.CPBreakpoint);
//LOG(COMMANDPROCESSOR,"!!! BP irq raised"); //LOG(COMMANDPROCESSOR,"!!! BP irq raised");
fifo.bFF_Breakpoint = 1; fifo.bFF_Breakpoint = 1;
m_CPStatusReg.Breakpoint = 1; m_CPStatusReg.Breakpoint = 1;
UpdateInterrupts(); UpdateInterrupts();
break; break;
@ -660,7 +660,7 @@ void CatchUpGPU()
// We are going to do FP math on the main thread so have to save the current state // We are going to do FP math on the main thread so have to save the current state
SaveSSEState(); SaveSSEState();
LoadDefaultSSEState(); LoadDefaultSSEState();
PluginVideo::Video_SendFifoData(ptr,32); CPluginManager::GetInstance().GetVideo()->Video_SendFifoData(ptr,32);
LoadSSEState(); LoadSSEState();
fifo.CPReadWriteDistance -= 32; fifo.CPReadWriteDistance -= 32;