From 1e7655b5dba9371bbb7afaf04b803c0d3cdde9d6 Mon Sep 17 00:00:00 2001 From: "memberTwo.mb2" Date: Sat, 24 Jan 2009 14:43:17 +0000 Subject: [PATCH] 1) XFB in DC proposal. This impact video plugin interface. WARNING: XFB_Draw is not CPU->VI dependent anymore. It's up to GP now. Except for some 2D homebrews which never use GPfifo&CP but direcly XFB. Well, in other words: emulated VSync is uncorrelated with CPU timings now. Tell me if it's too much hacky. 2) DC/GPfifo work: GP quicker to react. PeekMessages at a more steady rate. 3) Fix XFB address to avoid crash like with Animal Crossing gc. TODO: VI regs need proper typedef and logic. 4) Few misc. changes on the fly. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2001 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/PluginVideo.h | 2 +- Source/Core/Core/Src/Core.cpp | 2 +- Source/Core/Core/Src/HW/CommandProcessor.cpp | 10 ++- Source/Core/Core/Src/HW/CommandProcessor.h | 3 + Source/Core/Core/Src/HW/Memmap.cpp | 3 +- Source/Core/Core/Src/HW/VideoInterface.cpp | 63 ++++++++++++------- Source/Core/VideoCommon/Src/Fifo.cpp | 28 +++++++-- .../VideoCommon/Src/VertexLoader_Color.cpp | 20 +++--- Source/Core/VideoCommon/Src/VideoCommon.h | 7 +++ Source/PluginSpecs/pluginspecs_video.h | 2 +- Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 2 +- .../Plugins/Plugin_VideoOGL/Src/BPStructs.cpp | 8 ++- Source/Plugins/Plugin_VideoOGL/Src/XFB.cpp | 23 +++++++ Source/Plugins/Plugin_VideoOGL/Src/XFB.h | 3 + Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 19 ++++-- 15 files changed, 148 insertions(+), 47 deletions(-) diff --git a/Source/Core/Common/Src/PluginVideo.h b/Source/Core/Common/Src/PluginVideo.h index fae20d434f..70ae8f39ec 100644 --- a/Source/Core/Common/Src/PluginVideo.h +++ b/Source/Core/Common/Src/PluginVideo.h @@ -7,7 +7,7 @@ namespace Common { typedef void (__cdecl* TVideo_Prepare)(); typedef void (__cdecl* TVideo_SendFifoData)(u8*,u32); - typedef void (__cdecl* TVideo_UpdateXFB)(u8*, u32, u32, s32); + typedef void (__cdecl* TVideo_UpdateXFB)(u8*, u32, u32, s32, BOOL); typedef bool (__cdecl* TVideo_Screenshot)(const char* filename); typedef void (__cdecl* TVideo_EnterLoop)(); typedef void (__cdecl* TVideo_AddMessage)(const char* pstr, unsigned int milliseconds); diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index d7e1ca8aea..e4b363ee33 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -426,8 +426,8 @@ THREAD_RETURN EmuThread(void *pArg) } else { - cpuThread = new Common::Thread(CpuThread, pArg); Plugins.GetVideo()->Video_Prepare(); //wglMakeCurrent + cpuThread = new Common::Thread(CpuThread, pArg); Common::SetCurrentThreadName("Video thread"); Plugins.GetVideo()->Video_EnterLoop(); } diff --git a/Source/Core/Core/Src/HW/CommandProcessor.cpp b/Source/Core/Core/Src/HW/CommandProcessor.cpp index e1b0845556..3f14cfe4f6 100644 --- a/Source/Core/Core/Src/HW/CommandProcessor.cpp +++ b/Source/Core/Core/Src/HW/CommandProcessor.cpp @@ -151,6 +151,13 @@ u16 m_tokenReg; SCPFifoStruct fifo; //This one is shared between gfx thread and emulator thread static u32 fake_GPWatchdogLastToken = 0; +static BOOL fake_CommandProcessorNotUsed = TRUE; // This is used by VI when homebrews use directly XFB without FIFO and CP + +// hack: This is used by VI when homebrews use directly XFB without FIFO and CP +BOOL IsCommandProcessorNotUsed() +{ + return fake_CommandProcessorNotUsed; +} void DoState(PointerWrap &p) { @@ -221,7 +228,7 @@ void Init() fifo.CPReadIdle = 1; et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper); - + fake_CommandProcessorNotUsed = TRUE; } void Shutdown() @@ -411,6 +418,7 @@ void Write16(const u16 _Value, const u32 _Address) case CTRL_REGISTER: { + fake_CommandProcessorNotUsed = FALSE; UCPCtrlReg tmpCtrl(_Value); Common::SyncInterlockedExchange((LONG*)&fifo.bFF_GPReadEnable, tmpCtrl.GPReadEnable); diff --git a/Source/Core/Core/Src/HW/CommandProcessor.h b/Source/Core/Core/Src/HW/CommandProcessor.h index 312abe9774..58fff402b3 100644 --- a/Source/Core/Core/Src/HW/CommandProcessor.h +++ b/Source/Core/Core/Src/HW/CommandProcessor.h @@ -79,6 +79,9 @@ bool AllowIdleSkipping(); void IncrementGPWDToken(); void WaitForFrameFinish(); +// hack: This is used by VI when homebrews use directly XFB without FIFO and CP +BOOL IsCommandProcessorNotUsed(); + } // end of namespace CommandProcessor #endif diff --git a/Source/Core/Core/Src/HW/Memmap.cpp b/Source/Core/Core/Src/HW/Memmap.cpp index c4bf452da5..97726fa5d4 100644 --- a/Source/Core/Core/Src/HW/Memmap.cpp +++ b/Source/Core/Core/Src/HW/Memmap.cpp @@ -810,7 +810,8 @@ u8 *GetPointer(const u32 _Address) _dbg_assert_msg_(MEMMAP, 0, "Memory", "GetPointer from IO Bridge doesnt work"); return NULL; default: - PanicAlert("Tried to get pointer for unknown address %08x", _Address); + if (!PanicYesNo("Tried to get pointer for unknown address %08x\n Continue?", _Address)) + Crash(); break; } return NULL; diff --git a/Source/Core/Core/Src/HW/VideoInterface.cpp b/Source/Core/Core/Src/HW/VideoInterface.cpp index 2edca7312f..de14974faa 100644 --- a/Source/Core/Core/Src/HW/VideoInterface.cpp +++ b/Source/Core/Core/Src/HW/VideoInterface.cpp @@ -20,6 +20,8 @@ #include "../PowerPC/PowerPC.h" +#include "../Core.h" // <- for Core::GetStartupParameter().bUseDualCore +#include "CommandProcessor.h" // <- for homebrew's XFB draw hack #include "PeripheralInterface.h" #include "VideoInterface.h" #include "Memmap.h" @@ -513,30 +515,45 @@ void Update() u8* xfbPtr = 0; int yOffset = 0; - if (NextXFBRender == 1) + // (mb2) hack: We request XFB updates from CPUthread (here) only when homebrews use directly XFB without FIFO and CP + if (CommandProcessor::IsCommandProcessorNotUsed()) { - NextXFBRender = LinesPerField; - u32 addr = (VideoInterface::m_FrameBufferTop.Hex & 0xFFFFFFF); - if (VideoInterface::m_FrameBufferTop.Hex & 0x10000000) - addr = addr << 5; - xfbPtr = Memory::GetPointer(addr); - } - else - { - NextXFBRender = 1; - u32 addr = (VideoInterface::m_FrameBufferBottom.Hex & 0xFFFFFFF); - // check the top buffer address not the bottom - if (VideoInterface::m_FrameBufferTop.Hex & 0x10000000) - addr = addr << 5; - xfbPtr = Memory::GetPointer(addr); - yOffset = -1; - } - Common::PluginVideo* video = CPluginManager::GetInstance().GetVideo(); - if (xfbPtr && video->IsValid()) - { - int fbWidth = m_VIHorizontalStepping.FieldSteps * 16; - int fbHeight = (m_VIHorizontalStepping.FbSteps / m_VIHorizontalStepping.FieldSteps) * m_VIVerticalTimingRegister.ACV; - video->Video_UpdateXFB(xfbPtr, fbWidth, fbHeight, yOffset); + if (NextXFBRender == 1) + { + NextXFBRender = LinesPerField; + // TODO: proper VI regs typedef and logic for XFB to work. + // eg. Animal Crossing gc have smth in TFBL.XOF bitfield. + // "XOF - Horizontal Offset of the left-most pixel within the first word of the fetched picture." + u32 addr = (m_FrameBufferTop.Hex & 0x00FFFFFF); + if (m_FrameBufferTop.Hex & 0x10000000) + addr = addr << 5; + xfbPtr = Memory::GetPointer(addr); + _dbg_assert_msg_(VIDEOINTERFACE, xfbPtr, "Bad top XFB address"); + } + else + { + NextXFBRender = 1; + // TODO: proper VI regs typedef and logic for XFB to work. + u32 addr = (m_FrameBufferBottom.Hex & 0x00FFFFFF); + // check the top buffer address not the bottom <- (mb2) why not on the bottom one? + if (m_FrameBufferTop.Hex & 0x10000000) + addr = addr << 5; + xfbPtr = Memory::GetPointer(addr); + _dbg_assert_msg_(VIDEOINTERFACE, xfbPtr, "Bad bottom XFB address"); + yOffset = -1; + } + Common::PluginVideo* video = CPluginManager::GetInstance().GetVideo(); + if (xfbPtr && video->IsValid()) + { + int fbWidth = m_VIHorizontalStepping.FieldSteps * 16; + int fbHeight = (m_VIHorizontalStepping.FbSteps / m_VIHorizontalStepping.FieldSteps) * m_VIVerticalTimingRegister.ACV; + if (Core::GetStartupParameter().bUseDualCore) + // scheduled on EmuThread in DC mode + video->Video_UpdateXFB(xfbPtr, fbWidth, fbHeight, yOffset, TRUE); + else + // otherwise do it now from here (CPUthread) + video->Video_UpdateXFB(xfbPtr, fbWidth, fbHeight, yOffset, FALSE); + } } } diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index b848aa1f41..ea53bed0c2 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -25,7 +25,12 @@ extern u8* g_pVideoData; -bool fifoStateRun = true; +// TODO (mb2): move/rm this global +volatile BOOL g_XFBUpdateRequested = FALSE; + +#ifndef _WIN32 +static bool fifoStateRun = true; +#endif // STATE_TO_SAVE static u8 *videoBuffer; @@ -43,18 +48,25 @@ void Fifo_DoState(PointerWrap &p) void Fifo_Init() { videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE); +#ifndef _WIN32 fifoStateRun = true; +#endif + g_XFBUpdateRequested = FALSE; } void Fifo_Shutdown() { FreeMemoryPages(videoBuffer, FIFO_SIZE); +#ifndef _WIN32 fifoStateRun = false; +#endif } void Fifo_Stop() { +#ifndef _WIN32 fifoStateRun = false; +#endif } u8* FAKE_GetFifoStartPtr() @@ -97,20 +109,26 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) while (fifoStateRun) #endif { - if (_fifo.CPReadWriteDistance < _fifo.CPLoWatermark) + if (_fifo.CPReadWriteDistance == 0) Common::SleepCurrentThread(1); //etc... + if (g_XFBUpdateRequested) + { + Video_UpdateXFB(NULL, 0, 0, 0, FALSE); + g_XFBUpdateRequested = FALSE; + video_initialize.pCopiedToXFB(); + } // check if we are able to run this buffer if ((_fifo.bFF_GPReadEnable) && _fifo.CPReadWriteDistance && !(_fifo.bFF_BPEnable && _fifo.bFF_Breakpoint)) { Common::SyncInterlockedExchange((LONG*)&_fifo.CPReadIdle, 0); //video_initialize.pLog("RUN...........................",FALSE); int peek_counter = 0; - while (_fifo.bFF_GPReadEnable && (_fifo.CPReadWriteDistance > 0)) + while (_fifo.bFF_GPReadEnable && _fifo.CPReadWriteDistance) { peek_counter++; - if (peek_counter == 50) { + if (peek_counter == 1000) { video_initialize.pPeekMessages(); peek_counter = 0; } @@ -146,6 +164,8 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) #else // sending the whole CPReadWriteDistance distToSend = _fifo.CPReadWriteDistance; + // send 1024B chunk max lenght to have better control over PeekMessages' period + distToSend = distToSend > 1024 ? 1024 : distToSend; if ( (distToSend+readPtr) >= _fifo.CPEnd) // TODO: better? { distToSend =_fifo.CPEnd - readPtr; diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp b/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp index ebb1c62dcc..e204f927db 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp @@ -69,19 +69,21 @@ void _SetCol565(u16 val) ////////////////////////////////////////////////////////////////////////// inline u32 _Read24(u32 iAddress) { - u32 col = Memory_Read_U8(iAddress) << RSHIFT; //should just get a pointer to main memory instead of going thru slow memhandler - col |= Memory_Read_U8(iAddress+1) << GSHIFT; //we can guarantee that it is reading from main memory - col |= Memory_Read_U8(iAddress+2) << BSHIFT; - return col | (0xFF<