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:
parent
ba8c2aa7e4
commit
9dcb4edc97
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue