Skip to content

Commit

Permalink
Improve VBlank timing
Browse files Browse the repository at this point in the history
Some vblank wait methods can skip sleeping, if they are called inside or outside a vblank (according to their function).
  • Loading branch information
kernle32dll committed Mar 23, 2022
1 parent 7cffacb commit 8b40b30
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
29 changes: 29 additions & 0 deletions Source/iop/IopBios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#define BIOS_THREAD_LINK_HEAD_BASE (CIopBios::CONTROL_BLOCK_START + 0x0000)
#define BIOS_CURRENT_THREAD_ID_BASE (CIopBios::CONTROL_BLOCK_START + 0x0008)
#define BIOS_CURRENT_TIME_BASE (CIopBios::CONTROL_BLOCK_START + 0x0010)
#define BIOS_IN_VBLANK_BASE (CIopBios::CONTROL_BLOCK_START + 0x0014)
#define BIOS_MODULESTARTREQUEST_HEAD_BASE (CIopBios::CONTROL_BLOCK_START + 0x0018)
#define BIOS_MODULESTARTREQUEST_FREE_BASE (CIopBios::CONTROL_BLOCK_START + 0x0020)
#define BIOS_HANDLERS_BASE (CIopBios::CONTROL_BLOCK_START + 0x0100)
Expand Down Expand Up @@ -116,6 +117,7 @@ CIopBios::CIopBios(CMIPS& cpu, uint8* ram, uint32 ramSize, uint8* spr)
, m_vpls(reinterpret_cast<VPL*>(&m_ram[BIOS_VPL_BASE]), 1, MAX_VPL)
, m_loadedModules(reinterpret_cast<LOADEDMODULE*>(&m_ram[BIOS_LOADEDMODULE_BASE]), 1, MAX_LOADEDMODULE)
, m_currentThreadId(reinterpret_cast<uint32*>(m_ram + BIOS_CURRENT_THREAD_ID_BASE))
, m_inVBlank(reinterpret_cast<bool*>(m_ram + BIOS_IN_VBLANK_BASE))
{
static_assert(BIOS_CALCULATED_END <= CIopBios::CONTROL_BLOCK_END, "Control block size is too small");
static_assert(BIOS_SYSTEM_INTRHANDLER_TABLE_BASE > CIopBios::CONTROL_BLOCK_START, "Intr handler table is outside reserved block");
Expand Down Expand Up @@ -146,6 +148,7 @@ void CIopBios::Reset(const Iop::SifManPtr& sifMan)
CurrentTime() = 0xBE00000;
ThreadLinkHead() = 0;
m_currentThreadId = -1;
m_inVBlank = false;

m_cpu.m_State.nCOP0[CCOP_SCU::STATUS] |= CMIPS::STATUS_IE;

Expand Down Expand Up @@ -1692,6 +1695,30 @@ void CIopBios::SleepThreadTillVBlankEnd()
m_rescheduleNeeded = true;
}

void CIopBios::SleepThreadTillVBlank()
{
if(m_inVBlank)
{
return;
}
THREAD* thread = GetThread(m_currentThreadId);
thread->status = THREAD_STATUS_WAIT_VBLANK_START;
UnlinkThread(thread->id);
m_rescheduleNeeded = true;
}

void CIopBios::SleepThreadTillNonVBlank()
{
if(!m_inVBlank)
{
return;
}
THREAD* thread = GetThread(m_currentThreadId);
thread->status = THREAD_STATUS_WAIT_VBLANK_END;
UnlinkThread(thread->id);
m_rescheduleNeeded = true;
}

void CIopBios::LoadThreadContext(uint32 threadId)
{
THREAD* thread = GetThread(threadId);
Expand Down Expand Up @@ -1849,6 +1876,7 @@ void CIopBios::CountTicks(uint32 ticks)

void CIopBios::NotifyVBlankStart()
{
m_inVBlank = true;
for(auto thread : m_threads)
{
if(!thread) continue;
Expand All @@ -1862,6 +1890,7 @@ void CIopBios::NotifyVBlankStart()

void CIopBios::NotifyVBlankEnd()
{
m_inVBlank = false;
for(auto thread : m_threads)
{
if(!thread) continue;
Expand Down
3 changes: 3 additions & 0 deletions Source/iop/IopBios.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ class CIopBios : public Iop::CBiosBase
int32 FindVblankHandlerByLineAndPtr(uint32 startEnd, uint32 handlerPtr);
void SleepThreadTillVBlankStart();
void SleepThreadTillVBlankEnd();
void SleepThreadTillVBlank();
void SleepThreadTillNonVBlank();

uint32 CreateSemaphore(uint32, uint32, uint32, uint32);
uint32 DeleteSemaphore(uint32);
Expand Down Expand Up @@ -662,6 +664,7 @@ class CIopBios : public Iop::CBiosBase
IopModuleMapType m_modules;

OsVariableWrapper<uint32> m_currentThreadId;
OsVariableWrapper<bool> m_inVBlank;

#ifdef DEBUGGER_INCLUDED
BiosDebugModuleInfoArray m_moduleTags;
Expand Down
5 changes: 2 additions & 3 deletions Source/iop/Iop_Vblank.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,7 @@ int32 CVblank::WaitVblank()
#ifdef _DEBUG
CLog::GetInstance().Print(LOG_NAME, FUNCTION_WAITVBLANK "();\r\n");
#endif
//TODO: Skip waiting if we're already in Vblank
m_bios.SleepThreadTillVBlankStart();
m_bios.SleepThreadTillVBlank();
return 0;
}

Expand All @@ -118,7 +117,7 @@ int32 CVblank::WaitNonVblank()
#ifdef _DEBUG
CLog::GetInstance().Print(LOG_NAME, FUNCTION_WAITNONVBLANK "();\r\n");
#endif
m_bios.SleepThreadTillVBlankEnd();
m_bios.SleepThreadTillNonVBlank();
return 0;
}

Expand Down

0 comments on commit 8b40b30

Please sign in to comment.