Merge branch 'master' into GLSL-master

Conflicts:
	.gitignore
This commit is contained in:
degasus
2013-03-12 11:28:56 +01:00
87 changed files with 23863 additions and 38776 deletions

View File

@ -32,6 +32,8 @@
#include "HW/GPFifo.h"
#include "HW/Memmap.h"
#include "DLCache.h"
#include "HW/SystemTimers.h"
#include "Core.h"
namespace CommandProcessor
{
@ -57,12 +59,15 @@ static bool bProcessFifoAllDistance = false;
volatile bool isPossibleWaitingSetDrawDone = false;
volatile bool isHiWatermarkActive = false;
volatile bool isLoWatermarkActive = false;
volatile bool interruptSet= false;
volatile bool interruptWaiting= false;
volatile bool interruptTokenWaiting = false;
volatile bool interruptFinishWaiting = false;
volatile bool waitingForPEInterruptDisable = false;
volatile u32 VITicks = CommandProcessor::m_cpClockOrigin;
bool IsOnThread()
{
return SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread;
@ -88,6 +93,7 @@ void DoState(PointerWrap &p)
p.Do(bProcessFifoToLoWatermark);
p.Do(bProcessFifoAllDistance);
p.Do(isHiWatermarkActive);
p.Do(isLoWatermarkActive);
p.Do(isPossibleWaitingSetDrawDone);
p.Do(interruptSet);
p.Do(interruptWaiting);
@ -119,7 +125,7 @@ void Init()
m_tokenReg = 0;
memset(&fifo,0,sizeof(fifo));
fifo.CPCmdIdle = 1 ;
fifo.CPCmdIdle = 1;
fifo.CPReadIdle = 1;
fifo.bFF_Breakpoint = 0;
fifo.bFF_HiWatermark = 0;
@ -136,6 +142,7 @@ void Init()
bProcessFifoAllDistance = false;
isPossibleWaitingSetDrawDone = false;
isHiWatermarkActive = false;
isLoWatermarkActive = false;
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
}
@ -294,7 +301,6 @@ void Read16(u16& _rReturnValue, const u32 _Address)
void Write16(const u16 _Value, const u32 _Address)
{
INFO_LOG(COMMANDPROCESSOR, "(write16): 0x%04x @ 0x%08x",_Value,_Address);
switch (_Address & 0xFFF)
@ -405,7 +411,8 @@ void Write16(const u16 _Value, const u32 _Address)
{
GPFifo::ResetGatherPipe();
ResetVideoBuffer();
}else
}
else
{
ResetVideoBuffer();
}
@ -461,7 +468,7 @@ void STACKALIGN GatherPipeBursted()
}
if (IsOnThread())
SetOverflowStatusFromGatherPipe();
SetCpStatus();
// update the fifo-pointer
if (fifo.CPWritePointer >= fifo.CPEnd)
@ -511,19 +518,6 @@ void AbortFrame()
}
void SetOverflowStatusFromGatherPipe()
{
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
isHiWatermarkActive = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt && m_CPCtrlReg.GPReadEnable;
if (isHiWatermarkActive)
{
interruptSet = true;
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
}
}
void SetCpStatus()
{
// overflow & underflow check
@ -531,30 +525,33 @@ void SetCpStatus()
fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
// breakpoint
if (fifo.bFF_BPEnable)
{
if (fifo.CPBreakpoint == fifo.CPReadPointer)
{
if (!fifo.bFF_Breakpoint)
if (Core::IsGPUThread())
{
if (fifo.bFF_BPEnable)
{
if (fifo.CPBreakpoint == fifo.CPReadPointer)
{
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
fifo.bFF_Breakpoint = true;
IncrementCheckContextId();
if (!fifo.bFF_Breakpoint)
{
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
fifo.bFF_Breakpoint = true;
IncrementCheckContextId();
}
}
}
else
{
if (fifo.bFF_Breakpoint)
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
fifo.bFF_Breakpoint = false;
}
}
else
{
if (fifo.bFF_Breakpoint)
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
fifo.bFF_Breakpoint = false;
fifo.bFF_Breakpoint = false;
}
}
else
{
if (fifo.bFF_Breakpoint)
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
fifo.bFF_Breakpoint = false;
}
}
bool bpInt = fifo.bFF_Breakpoint && fifo.bFF_BPInt;
bool ovfInt = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt;
@ -562,17 +559,27 @@ void SetCpStatus()
bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable;
isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
isLoWatermarkActive = undfInt && m_CPCtrlReg.GPReadEnable;
if (interrupt != interruptSet && !interruptWaiting)
{
u64 userdata = interrupt?1:0;
if (IsOnThread())
{
if(!interrupt || bpInt || undfInt)
if(!interrupt || bpInt || undfInt || ovfInt)
{
interruptWaiting = true;
CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
if (Core::IsGPUThread())
{
interruptWaiting = true;
CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
}
else if (Core::IsCPUThread())
{
interruptSet = interrupt;
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, interrupt);
}
}
}
else
@ -596,7 +603,7 @@ void ProcessFifoAllDistance()
if (IsOnThread())
{
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt())
fifo.CPReadWriteDistance && !AtBreakpoint())
Common::YieldCPU();
}
bProcessFifoAllDistance = false;
@ -617,15 +624,11 @@ void SetCpStatusRegister()
{
// Here always there is one fifo attached to the GPU
m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint;
m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || (fifo.CPReadPointer == fifo.CPWritePointer) || (fifo.CPReadPointer == fifo.CPBreakpoint) ;
m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance;
m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || AtBreakpoint() || (fifo.CPReadPointer == fifo.CPWritePointer);
m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance || AtBreakpoint() || !fifo.bFF_GPReadEnable;
m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark;
m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark;
// HACK to compensate for slow response to PE interrupts in Time Splitters: Future Perfect
if (IsOnThread())
PixelEngine::ResumeWaitingForPEInterrupt();
INFO_LOG(COMMANDPROCESSOR,"\t Read from STATUS_REGISTER : %04x", m_CPStatusReg.Hex);
DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s"
, m_CPStatusReg.Breakpoint ? "ON" : "OFF"
@ -693,4 +696,12 @@ void SetCpClearRegister()
// }
}
void Update()
{
while (VITicks > m_cpClockOrigin && fifo.isGpuReadingData && IsOnThread())
Common::YieldCPU();
if (fifo.isGpuReadingData)
Common::AtomicAdd(VITicks, SystemTimers::GetTicksPerSecond() / 10000);
}
} // end of namespace CommandProcessor

View File

@ -31,6 +31,7 @@ namespace CommandProcessor
extern SCPFifoStruct fifo; //This one is shared between gfx thread and emulator thread.
extern volatile bool isPossibleWaitingSetDrawDone; //This one is used for sync gfx thread and emulator thread.
extern volatile bool isHiWatermarkActive;
extern volatile bool isLoWatermarkActive;
extern volatile bool interruptSet;
extern volatile bool interruptWaiting;
extern volatile bool interruptTokenWaiting;
@ -140,6 +141,9 @@ union UCPClearReg
UCPClearReg(u16 _hex) {Hex = _hex; }
};
// Can be any number, low enough to not be below the number of clocks executed by the GPU per CP_PERIOD
const static u32 m_cpClockOrigin = 200000;
// Init
void Init();
void Shutdown();
@ -161,11 +165,14 @@ bool AllowIdleSkipping();
void SetCpClearRegister();
void SetCpControlRegister();
void SetCpStatusRegister();
void SetOverflowStatusFromGatherPipe();
void ProcessFifoToLoWatermark();
void ProcessFifoAllDistance();
void ProcessFifoEvents();
void AbortFrame();
void Update();
extern volatile u32 VITicks;
} // namespace CommandProcessor
#endif // _COMMANDPROCESSOR_H

View File

@ -26,6 +26,7 @@
#include "Fifo.h"
#include "HW/Memmap.h"
#include "Core.h"
#include "CoreTiming.h"
volatile bool g_bSkipCurrentFrame = false;
extern u8* g_pVideoData;
@ -72,6 +73,7 @@ void Fifo_Init()
videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
size = 0;
GpuRunningState = false;
Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin);
}
void Fifo_Shutdown()
@ -123,7 +125,7 @@ void ReadDataFromFifo(u8* _uData, u32 len)
size -= pos;
if (size + len > FIFO_SIZE)
{
PanicAlert("FIFO out of bounds (sz = %i, at %08x)", size, pos);
PanicAlert("FIFO out of bounds (sz = %i, len = %i at %08x)", size, len, pos);
}
memmove(&videoBuffer[0], &videoBuffer[pos], size);
g_pVideoData = videoBuffer;
@ -147,6 +149,7 @@ void RunGpuLoop()
std::lock_guard<std::mutex> lk(m_csHWVidOccupied);
GpuRunningState = true;
SCPFifoStruct &fifo = CommandProcessor::fifo;
u32 cyclesExecuted = 0;
while (GpuRunningState)
{
@ -155,31 +158,41 @@ void RunGpuLoop()
VideoFifo_CheckAsyncRequest();
CommandProcessor::SetCpStatus();
Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin);
// check if we are able to run this buffer
while (GpuRunningState && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt())
while (GpuRunningState && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint())
{
if (!GpuRunningState) break;
fifo.isGpuReadingData = true;
CommandProcessor::isPossibleWaitingSetDrawDone = fifo.bFF_GPLinkEnable ? true : false;
u32 readPtr = fifo.CPReadPointer;
u8 *uData = Memory::GetPointer(readPtr);
if (readPtr == fifo.CPEnd) readPtr = fifo.CPBase;
if (Common::AtomicLoad(CommandProcessor::VITicks) > CommandProcessor::m_cpClockOrigin || !Core::g_CoreStartupParameter.bSyncGPU)
{
u32 readPtr = fifo.CPReadPointer;
u8 *uData = Memory::GetPointer(readPtr);
if (readPtr == fifo.CPEnd) readPtr = fifo.CPBase;
else readPtr += 32;
_assert_msg_(COMMANDPROCESSOR, (s32)fifo.CPReadWriteDistance - 32 >= 0 ,
"Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce inestabilty in the game. Please report it.", fifo.CPReadWriteDistance - 32);
ReadDataFromFifo(uData, 32);
OpcodeDecoder_Run(g_bSkipCurrentFrame);
Common::AtomicStore(fifo.CPReadPointer, readPtr);
Common::AtomicAdd(fifo.CPReadWriteDistance, -32);
if((GetVideoBufferEndPtr() - g_pVideoData) == 0)
Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
_assert_msg_(COMMANDPROCESSOR, (s32)fifo.CPReadWriteDistance - 32 >= 0 ,
"Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce instabilty in the game. Please report it.", fifo.CPReadWriteDistance - 32);
ReadDataFromFifo(uData, 32);
cyclesExecuted = OpcodeDecoder_Run(g_bSkipCurrentFrame);
if (Common::AtomicLoad(CommandProcessor::VITicks) > cyclesExecuted && Core::g_CoreStartupParameter.bSyncGPU)
Common::AtomicAdd(CommandProcessor::VITicks, -(s32)cyclesExecuted);
Common::AtomicStore(fifo.CPReadPointer, readPtr);
Common::AtomicAdd(fifo.CPReadWriteDistance, -32);
if((GetVideoBufferEndPtr() - g_pVideoData) == 0)
Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
}
CommandProcessor::SetCpStatus();
// This call is pretty important in DualCore mode and must be called in the FIFO Loop.
@ -188,7 +201,7 @@ void RunGpuLoop()
VideoFifo_CheckAsyncRequest();
CommandProcessor::isPossibleWaitingSetDrawDone = false;
}
fifo.isGpuReadingData = false;
@ -217,23 +230,23 @@ bool AtBreakpoint()
void RunGpu()
{
SCPFifoStruct &fifo = CommandProcessor::fifo;
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
{
u8 *uData = Memory::GetPointer(fifo.CPReadPointer);
SCPFifoStruct &fifo = CommandProcessor::fifo;
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
{
u8 *uData = Memory::GetPointer(fifo.CPReadPointer);
FPURoundMode::SaveSIMDState();
FPURoundMode::LoadDefaultSIMDState();
ReadDataFromFifo(uData, 32);
OpcodeDecoder_Run(g_bSkipCurrentFrame);
u32 count = OpcodeDecoder_Run(g_bSkipCurrentFrame);
FPURoundMode::LoadSIMDState();
//DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base");
//DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base");
if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase;
else fifo.CPReadPointer += 32;
if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase;
else fifo.CPReadPointer += 32;
fifo.CPReadWriteDistance -= 32;
}
CommandProcessor::SetCpStatus();
fifo.CPReadWriteDistance -= 32;
}
CommandProcessor::SetCpStatus();
}

View File

@ -23,7 +23,7 @@
class PointerWrap;
#define FIFO_SIZE (1024*1024)
#define FIFO_SIZE (2*1024*1024)
extern volatile bool g_bSkipCurrentFrame;

View File

@ -136,29 +136,38 @@ void ExecuteDisplayList(u32 address, u32 size)
InterpretDisplayList(address, size);
}
bool FifoCommandRunnable()
u32 FifoCommandRunnable(u32 &command_size)
{
u32 cycleTime = 0;
u32 buffer_size = (u32)(GetVideoBufferEndPtr() - g_pVideoData);
if (buffer_size == 0)
return false; // can't peek
return 0; // can't peek
u8 cmd_byte = DataPeek8(0);
u32 command_size = 0;
switch (cmd_byte)
{
case GX_NOP: // Hm, this means that we scan over nop streams pretty slowly...
command_size = 1;
cycleTime = 6;
break;
case GX_CMD_INVL_VC: // Invalidate Vertex Cache - no parameters
command_size = 1;
cycleTime = 6;
break;
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
command_size = 1;
cycleTime = 6;
break;
case GX_LOAD_BP_REG:
command_size = 5;
cycleTime = 12;
break;
case GX_LOAD_CP_REG:
command_size = 6;
cycleTime = 12;
break;
case GX_LOAD_INDX_A:
@ -166,10 +175,39 @@ bool FifoCommandRunnable()
case GX_LOAD_INDX_C:
case GX_LOAD_INDX_D:
command_size = 5;
cycleTime = 6; // TODO
break;
case GX_CMD_CALL_DL:
command_size = 9;
case GX_CMD_CALL_DL:
{
// FIXME: Calculate the cycle time of the display list.
//u32 address = DataPeek32(1);
//u32 size = DataPeek32(5);
//u8* old_pVideoData = g_pVideoData;
//u8* startAddress = Memory::GetPointer(address);
//// Avoid the crash if Memory::GetPointer failed ..
//if (startAddress != 0)
//{
// g_pVideoData = startAddress;
// u8 *end = g_pVideoData + size;
// u32 step = 0;
// while (g_pVideoData < end)
// {
// cycleTime += FifoCommandRunnable(step);
// g_pVideoData += step;
// }
//}
//else
//{
// cycleTime = 45;
//}
//// reset to the old pointer
//g_pVideoData = old_pVideoData;
command_size = 9;
cycleTime = 45; // This is unverified
}
break;
case GX_LOAD_XF_REG:
@ -180,11 +218,12 @@ bool FifoCommandRunnable()
command_size = 1 + 4;
u32 Cmd2 = DataPeek32(1);
int transfer_size = ((Cmd2 >> 16) & 15) + 1;
command_size += transfer_size * 4;
command_size += transfer_size * 4;
cycleTime = 18 + 6 * transfer_size;
}
else
{
return false;
return 0;
}
}
break;
@ -198,10 +237,11 @@ bool FifoCommandRunnable()
command_size = 1 + 2;
u16 numVertices = DataPeek16(1);
command_size += numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK);
cycleTime = 1600; // This depends on the number of pixels rendered
}
else
{
return false;
return 0;
}
}
else
@ -248,11 +288,19 @@ bool FifoCommandRunnable()
}
if (command_size > buffer_size)
return false;
return 0;
// INFO_LOG("OP detected: cmd_byte 0x%x size %i buffer %i",cmd_byte, command_size, buffer_size);
if (cycleTime == 0)
cycleTime = 6;
return true;
return cycleTime;
}
u32 FifoCommandRunnable()
{
u32 command_size = 0;
return FifoCommandRunnable(command_size);
}
static void Decode()
@ -461,16 +509,15 @@ void OpcodeDecoder_Shutdown()
}
}
void OpcodeDecoder_Run(bool skipped_frame)
u32 OpcodeDecoder_Run(bool skipped_frame)
{
if (!skipped_frame)
u32 totalCycles = 0;
u32 cycles = FifoCommandRunnable();
while (cycles > 0)
{
while (FifoCommandRunnable())
Decode();
}
else
{
while (FifoCommandRunnable())
DecodeSemiNop();
skipped_frame ? DecodeSemiNop() : Decode();
totalCycles += cycles;
cycles = FifoCommandRunnable();
}
return totalCycles;
}

View File

@ -50,6 +50,6 @@ extern bool g_bRecordFifoData;
void OpcodeDecoder_Init();
void OpcodeDecoder_Shutdown();
void OpcodeDecoder_Run(bool skipped_frame);
u32 OpcodeDecoder_Run(bool skipped_frame);
void ExecuteDisplayList(u32 address, u32 size);
#endif // _OPCODE_DECODING_H

View File

@ -33,7 +33,6 @@
#include "HW/ProcessorInterface.h"
#include "DLCache.h"
#include "State.h"
#include "PerfQueryBase.h"
namespace PixelEngine
{
@ -113,14 +112,14 @@ static UPEAlphaReadReg m_AlphaRead;
static UPECtrlReg m_Control;
//static u16 m_Token; // token value most recently encountered
static bool g_bSignalTokenInterrupt;
static bool g_bSignalFinishInterrupt;
volatile u32 g_bSignalTokenInterrupt;
volatile u32 g_bSignalFinishInterrupt;
static int et_SetTokenOnMainThread;
static int et_SetFinishOnMainThread;
volatile bool interruptSetToken = false;
volatile bool interruptSetFinish = false;
volatile u32 interruptSetToken = 0;
volatile u32 interruptSetFinish = 0;
u16 bbox[4];
bool bbox_active;
@ -164,10 +163,10 @@ void Init()
m_AlphaModeConf.Hex = 0;
m_AlphaRead.Hex = 0;
g_bSignalTokenInterrupt = false;
g_bSignalFinishInterrupt = false;
interruptSetToken = false;
interruptSetFinish = false;
g_bSignalTokenInterrupt = 0;
g_bSignalFinishInterrupt = 0;
interruptSetToken = 0;
interruptSetFinish = 0;
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread);
@ -214,7 +213,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
break;
case PE_TOKEN_REG:
_uReturnValue = CommandProcessor::fifo.PEToken;
_uReturnValue = Common::AtomicLoad(*(volatile u32*)&CommandProcessor::fifo.PEToken);
INFO_LOG(PIXELENGINE, "(r16) TOKEN_REG : %04x", _uReturnValue);
break;
@ -351,8 +350,8 @@ void Write16(const u16 _iValue, const u32 _iAddress)
{
UPECtrlReg tmpCtrl(_iValue);
if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = false;
if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = false;
if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = 0;
if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = 0;
m_Control.PETokenEnable = tmpCtrl.PETokenEnable;
m_Control.PEFinishEnable = tmpCtrl.PEFinishEnable;
@ -398,14 +397,14 @@ void UpdateInterrupts()
void UpdateTokenInterrupt(bool active)
{
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active);
interruptSetToken = active;
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active);
Common::AtomicStore(interruptSetToken, active ? 1 : 0);
}
void UpdateFinishInterrupt(bool active)
{
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
interruptSetFinish = active;
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
Common::AtomicStore(interruptSetFinish, active ? 1 : 0);
}
// TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate).
@ -415,20 +414,23 @@ void UpdateFinishInterrupt(bool active)
// Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
{
//if (userdata >> 16)
//{
g_bSignalTokenInterrupt = true;
//_dbg_assert_msg_(PIXELENGINE, (CommandProcessor::fifo.PEToken == (userdata&0xFFFF)), "WTF? BPMEM_PE_TOKEN_INT_ID's token != BPMEM_PE_TOKEN_ID's token" );
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken);
// XXX: No 16-bit atomic store available, so cheat and use 32-bit.
// That's what we've always done. We're counting on fifo.PEToken to be
// 4-byte padded.
Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, userdata & 0xffff);
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken);
if (userdata >> 16)
{
Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1);
UpdateInterrupts();
CommandProcessor::interruptTokenWaiting = false;
IncrementCheckContextId();
//}
}
CommandProcessor::interruptTokenWaiting = false;
IncrementCheckContextId();
}
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
{
g_bSignalFinishInterrupt = 1;
Common::AtomicStore(*(volatile u32*)&g_bSignalFinishInterrupt, 1);
UpdateInterrupts();
CommandProcessor::interruptFinishWaiting = false;
CommandProcessor::isPossibleWaitingSetDrawDone = false;
@ -438,23 +440,13 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
// THIS IS EXECUTED FROM VIDEO THREAD
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
{
// TODO?: set-token-value and set-token-INT could be merged since set-token-INT own the token value.
if (_bSetTokenAcknowledge) // set token INT
{
Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1);
}
Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token);
CommandProcessor::interruptTokenWaiting = true;
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
}
else // set token value
{
// we do it directly from videoThread because of
// Super Monkey Ball
// XXX: No 16-bit atomic store available, so cheat and use 32-bit.
// That's what we've always done. We're counting on fifo.PEToken to be
// 4-byte padded.
Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token);
}
CommandProcessor::interruptTokenWaiting = true;
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
IncrementCheckContextId();
}
@ -477,7 +469,6 @@ void ResetSetFinish()
{
UpdateFinishInterrupt(false);
g_bSignalFinishInterrupt = false;
}
else
{
@ -491,8 +482,7 @@ void ResetSetToken()
if (g_bSignalTokenInterrupt)
{
UpdateTokenInterrupt(false);
g_bSignalTokenInterrupt = false;
g_bSignalTokenInterrupt = 0;
}
else
{
@ -500,17 +490,4 @@ void ResetSetToken()
}
CommandProcessor::interruptTokenWaiting = false;
}
bool WaitingForPEInterrupt()
{
return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || interruptSetFinish || interruptSetToken);
}
void ResumeWaitingForPEInterrupt()
{
interruptSetFinish = false;
interruptSetToken = false;
CommandProcessor::interruptFinishWaiting = false;
CommandProcessor::interruptTokenWaiting = false;
}
} // end of namespace PixelEngine

View File

@ -81,8 +81,6 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
void SetFinish(void);
void ResetSetFinish(void);
void ResetSetToken(void);
bool WaitingForPEInterrupt();
void ResumeWaitingForPEInterrupt();
// Bounding box functionality. Paper Mario (both) are a couple of the few games that use it.
extern u16 bbox[4];