diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index eaafc2a74e..d46d2bf443 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -330,6 +330,7 @@ THREAD_RETURN EmuThread(void *pArg) VideoInitialize.pSetInterrupt = ProcessorInterface::SetInterrupt; VideoInitialize.pRegisterEvent = CoreTiming::RegisterEvent; VideoInitialize.pScheduleEvent_Threadsafe = CoreTiming::ScheduleEvent_Threadsafe; + VideoInitialize.pRemoveEvent = CoreTiming::RemoveAllEvents; // This is first the m_Panel handle, then it is updated to have the new window handle VideoInitialize.pWindowHandle = _CoreParameter.hMainWindow; VideoInitialize.pLog = Callback_VideoLog; diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp index 8dd4dcbbd7..50c3f33b34 100644 --- a/Source/Core/Core/Src/CoreTiming.cpp +++ b/Source/Core/Core/Src/CoreTiming.cpp @@ -96,6 +96,13 @@ void FreeEvent(Event* ev) eventPool = ev; } +void FreeTsEvent(Event* ev) +{ + ev->next = eventTsPool; + eventTsPool = ev; + allocatedTsEvents--; +} + int RegisterEvent(const char *name, TimedCallback callback) { EventType type; @@ -302,10 +309,13 @@ bool IsScheduled(int event_type) void RemoveEvent(int event_type) { + if (!first) return; if (first->type == event_type) { + if (event_type == 24) + NOTICE_LOG(FILEMON, "REMOVE 24"); Event *next = first->next; FreeEvent(first); first = next; @@ -318,6 +328,8 @@ void RemoveEvent(int event_type) { if (ptr->type == event_type) { + if (event_type == 24) + NOTICE_LOG(FILEMON, "REMOVE 24"); prev->next = ptr->next; FreeEvent(ptr); ptr = prev->next; @@ -330,6 +342,46 @@ void RemoveEvent(int event_type) } } +void RemoveThreadsafeEvent(int event_type) +{ + if (!tsFirst) + return; + if (tsFirst->type == event_type) + { + if (event_type == 24) + NOTICE_LOG(FILEMON, "REMOVE 24"); + Event *next = tsFirst->next; + FreeTsEvent(tsFirst); + tsFirst = next; + } + if (!tsFirst) + return; + Event *prev = tsFirst; + Event *ptr = prev->next; + while (ptr) + { + if (ptr->type == event_type) + { + if (event_type == 24) + NOTICE_LOG(FILEMON, "REMOVE 24"); + prev->next = ptr->next; + FreeTsEvent(ptr); + ptr = prev->next; + } + else + { + prev = ptr; + ptr = ptr->next; + } + } +} + +void RemoveAllEvents(int event_type) +{ + RemoveThreadsafeEvent(event_type); + RemoveEvent(event_type); +} + void SetMaximumSlice(int maximumSliceLength) { maxSliceLength = maximumSliceLength; diff --git a/Source/Core/Core/Src/CoreTiming.h b/Source/Core/Core/Src/CoreTiming.h index 1b40749882..7d5a89c846 100644 --- a/Source/Core/Core/Src/CoreTiming.h +++ b/Source/Core/Core/Src/CoreTiming.h @@ -62,6 +62,8 @@ void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata=0); // We only permit one event of each type in the queue at a time. void RemoveEvent(int event_type); +void RemoveThreadsafeEvent(int event_type); +void RemoveAllEvents(int event_type); bool IsScheduled(int event_type); void Advance(); void MoveEvents(); diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp index 39da6aeb6f..0bc11714b5 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp @@ -77,7 +77,7 @@ #include "Fifo.h" #include "ChunkFile.h" #include "CommandProcessor.h" - +#include "PixelEngine.h" namespace CommandProcessor { @@ -411,6 +411,14 @@ void Write16(const u16 _Value, const u32 _Address) m_CPStatusReg.OverflowHiWatermark = false; UpdateInterrupts(); + + // If the new fifo is being attached We make sure there wont be SetFinish event pending. + // This protection fix eternal darkness booting, because the second SetFinish event when it is booting + // seems invalid or has a bug and hang the game. + if (!fifo.bFF_GPReadEnable && tmpCtrl.GPReadEnable && !tmpCtrl.BPEnable) + { + PixelEngine::ResetSetFinish(); + } fifo.bFF_BPInt = tmpCtrl.BPInt; fifo.bFF_BPEnable = tmpCtrl.BPEnable; diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 8bfe6a314e..12f353f7e7 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -377,4 +377,20 @@ void SetFinish() INFO_LOG(PIXELENGINE, "VIDEO Set Finish"); } +//This function is used in CommandProcessor when write CTRL_REGISTER and the new fifo is attached. +void ResetSetFinish() +{ + //if SetFinish happened but PE_CTRL_REGISTER not, I reset the interrupt else + //remove event from the queque + if (g_bSignalFinishInterrupt) + { + g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, false); + g_bSignalFinishInterrupt = false; + + }else + { + g_VideoInitialize.pRemoveEvent(et_SetFinishOnMainThread); + } +} + } // end of namespace PixelEngine diff --git a/Source/Core/VideoCommon/Src/PixelEngine.h b/Source/Core/VideoCommon/Src/PixelEngine.h index 0043f16b8e..6124c7b6e3 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.h +++ b/Source/Core/VideoCommon/Src/PixelEngine.h @@ -67,6 +67,7 @@ void Write32(const u32 _iValue, const u32 _iAddress); // gfx plugin support void SetToken(const u16 _token, const int _bSetTokenAcknowledge); void SetFinish(void); +void ResetSetFinish(void); bool AllowIdleSkipping(); // Bounding box functionality. Paper Mario (both) are a couple of the few games that use it. diff --git a/Source/PluginSpecs/pluginspecs_video.h b/Source/PluginSpecs/pluginspecs_video.h index 57b7828953..6388db13a0 100644 --- a/Source/PluginSpecs/pluginspecs_video.h +++ b/Source/PluginSpecs/pluginspecs_video.h @@ -14,6 +14,7 @@ typedef void (*TimedCallback)(u64 userdata, int cyclesLate); typedef void (*TSetInterrupt)(u32 _causemask, bool _bSet); typedef int (*TRegisterEvent)(const char *name, TimedCallback callback); typedef void (*TScheduleEvent_Threadsafe)(int cyclesIntoFuture, int event_type, u64 userdata, bool fifoWait); +typedef void (*TRemoveEvent)(int event_type); typedef unsigned char* (*TGetMemoryPointer)(const unsigned int _iAddress); typedef void (*TVideoLog)(const char* _pMessage, int _bBreak); typedef void (*TSysMessage)(const char *fmt, ...); @@ -74,6 +75,7 @@ typedef struct TSetInterrupt pSetInterrupt; TRegisterEvent pRegisterEvent; TScheduleEvent_Threadsafe pScheduleEvent_Threadsafe; + TRemoveEvent pRemoveEvent; TGetMemoryPointer pGetMemoryPointer; TVideoLog pLog; TSysMessage pSysMessage;