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

View File

@ -23,10 +23,10 @@
// - ZWW as Crazy Taxi: PEfinish (GXSetDrawDone)
// - SMS: BP, PEToken, PEfinish
// - 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?
// - 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.
// 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.
@ -34,8 +34,8 @@
// *What I guess (thx to asynchronous DualCore mode):
// 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.
// The frame setting (by GP) took too much time and didn't finish properly due to this watchdog.
// (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.
// Faster GX plugins required, indeed :p
// * BPs are needed for some game GP/CPU sync.
@ -68,9 +68,9 @@
// * Cleanup of messy now unnecessary safety code in jit
#include "Common.h"
#include "../Plugins/Plugin_Video.h"
#include "../PowerPC/PowerPC.h"
#include "../CoreTiming.h"
#include "../PluginManager.h"
#include "MathUtil.h"
#include "Thread.h"
@ -90,7 +90,7 @@ namespace CommandProcessor
// Fifo Status Register
union UCPStatusReg
{
struct
struct
{
unsigned OverflowHiWatermark : 1;
unsigned UnderflowLoWatermark : 1;
@ -107,7 +107,7 @@ union UCPStatusReg
// Fifo Control Register
union UCPCtrlReg
{
struct
struct
{
unsigned GPReadEnable : 1;
unsigned CPIntEnable : 1;
@ -125,7 +125,7 @@ union UCPCtrlReg
// Fifo Control Register
union UCPClearReg
{
struct
struct
{
unsigned ClearFifoOverflow : 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))
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;
// TODO: cases cleanup
case FIFO_RW_DISTANCE_LO:
//_rReturnValue = ReadLow (fifo.CPReadWriteDistance);
case FIFO_RW_DISTANCE_LO:
//_rReturnValue = ReadLow (fifo.CPReadWriteDistance);
// hack: CPU will always believe fifo is empty and on idle
_rReturnValue = 0;
_rReturnValue = 0;
LOG(COMMANDPROCESSOR,"read FIFO_RW_DISTANCE_LO : %04x", _rReturnValue);
return;
case FIFO_RW_DISTANCE_HI:
//_rReturnValue = ReadHigh(fifo.CPReadWriteDistance);
case FIFO_RW_DISTANCE_HI:
//_rReturnValue = ReadHigh(fifo.CPReadWriteDistance);
// hack: CPU will always believe fifo is empty and on idle
_rReturnValue = 0;
_rReturnValue = 0;
LOG(COMMANDPROCESSOR,"read FIFO_RW_DISTANCE_HI : %04x", _rReturnValue);
return;
case FIFO_WRITE_POINTER_LO:
_rReturnValue = ReadLow (fifo.CPWritePointer);
case FIFO_WRITE_POINTER_LO:
_rReturnValue = ReadLow (fifo.CPWritePointer);
LOG(COMMANDPROCESSOR,"read FIFO_WRITE_POINTER_LO : %04x", _rReturnValue);
return;
case FIFO_WRITE_POINTER_HI:
_rReturnValue = ReadHigh(fifo.CPWritePointer);
case FIFO_WRITE_POINTER_HI:
_rReturnValue = ReadHigh(fifo.CPWritePointer);
LOG(COMMANDPROCESSOR,"read FIFO_WRITE_POINTER_HI : %04x", _rReturnValue);
return;
case FIFO_READ_POINTER_LO:
//_rReturnValue = ReadLow (fifo.CPReadPointer);
case FIFO_READ_POINTER_LO:
//_rReturnValue = ReadLow (fifo.CPReadPointer);
// 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);
return;
case FIFO_READ_POINTER_HI:
//_rReturnValue = ReadHigh(fifo.CPReadPointer);
case FIFO_READ_POINTER_HI:
//_rReturnValue = ReadHigh(fifo.CPReadPointer);
// 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);
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
// 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
// So I let the hack for now.
// So I let the hack for now.
// TODO (mb2): fix this!
// BP interrupt is cleared here
@ -464,75 +464,75 @@ void Write16(const u16 _Value, const u32 _Address)
break;
// Fifo Registers
case FIFO_TOKEN_REGISTER:
m_tokenReg = _Value;
case FIFO_TOKEN_REGISTER:
m_tokenReg = _Value;
LOG(COMMANDPROCESSOR,"\t write to FIFO_TOKEN_REGISTER : %04x", _Value);
break;
case FIFO_BASE_LO:
WriteLow ((u32 &)fifo.CPBase, _Value);
fifo.CPBase &= 0xFFFFFFE0;
WriteLow ((u32 &)fifo.CPBase, _Value);
fifo.CPBase &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO : %04x", _Value);
break;
case FIFO_BASE_HI:
WriteHigh((u32 &)fifo.CPBase, _Value);
fifo.CPBase &= 0xFFFFFFE0;
WriteHigh((u32 &)fifo.CPBase, _Value);
fifo.CPBase &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI : %04x", _Value);
break;
case FIFO_END_LO:
WriteLow ((u32 &)fifo.CPEnd, _Value);
fifo.CPEnd &= 0xFFFFFFE0;
WriteLow ((u32 &)fifo.CPEnd, _Value);
fifo.CPEnd &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO : %04x", _Value);
break;
case FIFO_END_HI:
WriteHigh((u32 &)fifo.CPEnd, _Value);
fifo.CPEnd &= 0xFFFFFFE0;
WriteHigh((u32 &)fifo.CPEnd, _Value);
fifo.CPEnd &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_END_HI : %04x", _Value);
break;
// Hm. Should we really & these with FFFFFFE0?
// (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.
case FIFO_WRITE_POINTER_LO:
WriteLow ((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0;
case FIFO_WRITE_POINTER_LO:
WriteLow ((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO : %04x", _Value);
break;
case FIFO_WRITE_POINTER_HI:
WriteHigh((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0;
case FIFO_WRITE_POINTER_HI:
WriteHigh((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI : %04x", _Value);
break;
case FIFO_READ_POINTER_LO:
WriteLow ((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0;
case FIFO_READ_POINTER_LO:
WriteLow ((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO : %04x", _Value);
break;
case FIFO_READ_POINTER_HI:
WriteHigh((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0;
case FIFO_READ_POINTER_HI:
WriteHigh((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0;
LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI : %04x", _Value);
break;
case FIFO_HI_WATERMARK_LO:
WriteLow ((u32 &)fifo.CPHiWatermark, _Value);
case FIFO_HI_WATERMARK_LO:
WriteLow ((u32 &)fifo.CPHiWatermark, _Value);
LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_LO : %04x", _Value);
break;
case FIFO_HI_WATERMARK_HI:
WriteHigh((u32 &)fifo.CPHiWatermark, _Value);
case FIFO_HI_WATERMARK_HI:
WriteHigh((u32 &)fifo.CPHiWatermark, _Value);
LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_HI : %04x", _Value);
break;
case FIFO_LO_WATERMARK_LO:
WriteLow ((u32 &)fifo.CPLoWatermark, _Value);
case FIFO_LO_WATERMARK_LO:
WriteLow ((u32 &)fifo.CPLoWatermark, _Value);
LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_LO : %04x", _Value);
break;
case FIFO_LO_WATERMARK_HI:
WriteHigh((u32 &)fifo.CPLoWatermark, _Value);
case FIFO_LO_WATERMARK_HI:
WriteHigh((u32 &)fifo.CPLoWatermark, _Value);
LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_HI : %04x", _Value);
break;
case FIFO_BP_LO:
WriteLow ((u32 &)fifo.CPBreakpoint, _Value);
WriteLow ((u32 &)fifo.CPBreakpoint, _Value);
LOG(COMMANDPROCESSOR,"write to FIFO_BP_LO : %04x", _Value);
break;
case FIFO_BP_HI:
WriteHigh((u32 &)fifo.CPBreakpoint, _Value);
WriteHigh((u32 &)fifo.CPBreakpoint, _Value);
LOG(COMMANDPROCESSOR,"write to FIFO_BP_HI : %04x", _Value);
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.
// So, we can skip it.
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);
break;
case FIFO_RW_DISTANCE_LO:
case FIFO_RW_DISTANCE_LO:
//WriteLow((u32 &)fifo.CPReadWriteDistance, _Value);
LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_LO : %04x", _Value);
break;
@ -576,7 +576,7 @@ void STACKALIGN GatherPipeBursted()
{
// update the fifo-pointer
fifo.CPWritePointer += GPFifo::GATHER_PIPE_SIZE;
if (fifo.CPWritePointer >= fifo.CPEnd)
if (fifo.CPWritePointer >= fifo.CPEnd)
fifo.CPWritePointer = fifo.CPBase;
Common::SyncInterlockedExchangeAdd((LONG*)&fifo.CPReadWriteDistance, GPFifo::GATHER_PIPE_SIZE);
@ -594,7 +594,7 @@ void STACKALIGN GatherPipeBursted()
// - @ game start -> watermark init: Overflow enabled, Underflow disabled
// - if (OV is raised)
// - 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
// - if (Underflow is raised (implicite: AND if an OV has been raised))
// - CPU can write to fifo
@ -618,7 +618,7 @@ void STACKALIGN GatherPipeBursted()
else
{
fifo.CPWritePointer += GPFifo::GATHER_PIPE_SIZE;
if (fifo.CPWritePointer >= fifo.CPEnd)
if (fifo.CPWritePointer >= fifo.CPEnd)
fifo.CPWritePointer = fifo.CPBase;
// check if we are in 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);
//LOG(COMMANDPROCESSOR,"!!! BP irq raised");
fifo.bFF_Breakpoint = 1;
fifo.bFF_Breakpoint = 1;
m_CPStatusReg.Breakpoint = 1;
UpdateInterrupts();
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
SaveSSEState();
LoadDefaultSSEState();
PluginVideo::Video_SendFifoData(ptr,32);
CPluginManager::GetInstance().GetVideo()->Video_SendFifoData(ptr,32);
LoadSSEState();
fifo.CPReadWriteDistance -= 32;