Attempt to calculate actual refresh rate (i.e. a CPU-GPU synced Mhz), no real success. Anybody have any ideas?
Is there no indication from the game when the screen refresh should occur? No, not what I could find, we currently calculate the refresh rate and m_VBeamPos from the CPU ticks progress. That works perfectly if the CPU and GPU is perfectly synced as in the single core and no-idle skipping mode. So I guess it's possible that the game doesn't indicate when the screen should be refreshed, but rather that the hardware calculate that from the CPU ticks progress. That leaves us with a problem in the dual core and idle skipping modes to calculate a CPU-GPU synced CPU ticks progress. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3447 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
3295ec38eb
commit
5c04af50a4
|
@ -94,12 +94,14 @@ void CMixer::PushSamples(short *samples, int num_stereo_samples, int core_sample
|
|||
if (!m_throttle)
|
||||
return;
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// The auto throttle function. This loop will put a ceiling on the CPU MHz.
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
/* This is only needed for non-AX sound, currently directly
|
||||
streamed and DTK sound. For AX we call SoundStream::Update in
|
||||
AXTask() for example. */
|
||||
while (m_queueSize > queue_maxlength / 2) {
|
||||
|
||||
while (m_queueSize > queue_maxlength / 2)
|
||||
{
|
||||
// Urgh.
|
||||
if (g_dspInitialize.pEmulatorState) {
|
||||
if (*g_dspInitialize.pEmulatorState != 0)
|
||||
|
@ -108,6 +110,7 @@ void CMixer::PushSamples(short *samples, int num_stereo_samples, int core_sample
|
|||
soundStream->Update();
|
||||
Common::SleepCurrentThread(0);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
push_sync.Enter();
|
||||
while (num_stereo_samples) {
|
||||
|
|
|
@ -111,6 +111,17 @@ void MatrixMul(int n, const float *a, const float *b, float *result)
|
|||
}
|
||||
}
|
||||
|
||||
// Calculate sum of a float list
|
||||
float MathFloatVectorSum(std::vector<float> Vec)
|
||||
{
|
||||
float Sum = 0.0;
|
||||
for(int i = 0; i < Vec.size(); i++)
|
||||
{
|
||||
Sum += Vec.at(i);
|
||||
}
|
||||
return Sum;
|
||||
}
|
||||
|
||||
void Matrix33::LoadIdentity(Matrix33 &mtx)
|
||||
{
|
||||
memset(mtx.data, 0, sizeof(mtx.data));
|
||||
|
|
|
@ -121,6 +121,7 @@ inline double pow2(double x) {return x * x;}
|
|||
void SaveSSEState();
|
||||
void LoadSSEState();
|
||||
void LoadDefaultSSEState();
|
||||
float MathFloatVectorSum(std::vector<float>);
|
||||
|
||||
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "Timer.h"
|
||||
#include "Common.h"
|
||||
#include "StringUtil.h"
|
||||
#include "MathUtil.h"
|
||||
|
||||
#include "Console.h"
|
||||
#include "Core.h"
|
||||
|
@ -672,23 +673,43 @@ void Callback_VideoCopiedToXFB()
|
|||
|
||||
frames++;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Custom frame limiter
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
if (targetfps > 0)
|
||||
{
|
||||
new_frametime = Timer.GetTimeDifference() - old_frametime;
|
||||
|
||||
old_frametime = Timer.GetTimeDifference();
|
||||
|
||||
wait_frametime = (1000/targetfps) - (u16)new_frametime;
|
||||
if (targetfps < 35)
|
||||
wait_frametime--;
|
||||
if (wait_frametime > 0)
|
||||
Common::SleepCurrentThread(wait_frametime*2);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Is it possible to calculate the CPU-GPU synced ticks for the dual core mode too?
|
||||
// And possible the idle skipping mode too?
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
static int Diff = 0, DistOld = 0;
|
||||
Diff = CommandProcessor::fifo.CPReadWriteDistance - DistOld;
|
||||
// If the CPReadWriteDistance has increased since the last frame we assume the CPU has raced
|
||||
// ahead of the GPU and we adjust the ticks. Why multiply the difference with 700? I don't know,
|
||||
// please fix it if possible.
|
||||
if (Diff > 0) VideoInterface::SyncTicksProgress -= Diff * 700;
|
||||
DistOld = CommandProcessor::fifo.CPReadWriteDistance;
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
if (Timer.GetTimeDifference() >= 1000)
|
||||
{
|
||||
old_frametime=0;
|
||||
// Time passed
|
||||
float t = (float)(Timer.GetTimeDifference()) / 1000.f;
|
||||
|
||||
// Use extended or summary information. The summary information does not print the ticks data,
|
||||
// that's more of a debugging interest, it can always be optional of course if someone is interested.
|
||||
//#define EXTENDED_INFO
|
||||
#ifdef EXTENDED_INFO
|
||||
u64 newTicks = CoreTiming::GetTicks();
|
||||
u64 newIdleTicks = CoreTiming::GetIdleTicks();
|
||||
|
||||
|
@ -698,11 +719,53 @@ void Callback_VideoCopiedToXFB()
|
|||
ticks = newTicks;
|
||||
idleTicks = newIdleTicks;
|
||||
|
||||
float t = (float)(Timer.GetTimeDifference()) / 1000.f;
|
||||
float TicksPercentage = (float)diff / (float)(SystemTimers::GetTicksPerSecond() / 1000000) * 100;
|
||||
#endif
|
||||
|
||||
char temp[256];
|
||||
sprintf(temp, "FPS:%8.2f - Core: %s | %s - Speed: %i MHz [Real: %i + IdleSkip: %i] / %i MHz",
|
||||
(float)frames / t,
|
||||
float FPS = (float)frames / t;
|
||||
float FPS_To_VPS_Rate = ((float)FPS / VideoInterface::ActualRefreshRate);
|
||||
// ---------------------------------------------------------------------
|
||||
// For the sake of the dual core mode calculate an average to somewhat reduce the variations
|
||||
// in the FPS/VPS rate
|
||||
// ______________________________
|
||||
/**/
|
||||
if (_CoreParameter.bUseDualCore)
|
||||
{
|
||||
static std::vector <float> FPSVPSList;
|
||||
static float AverageOver = 5.0;
|
||||
if (FPSVPSList.size() == AverageOver) FPSVPSList.erase(FPSVPSList.begin());
|
||||
FPSVPSList.push_back(FPS_To_VPS_Rate);
|
||||
if (FPSVPSList.size() == AverageOver)
|
||||
FPS_To_VPS_Rate = MathFloatVectorSum(FPSVPSList) / AverageOver;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Correct the FPS/VPS rate for temporary CPU-GPU timing variations. This rate can only be 1/Integer
|
||||
// so we set it to either 0.33, 0.5 or 1.0 depending on which it's closest to.
|
||||
/*
|
||||
1. Notice: This rate can currently not be calculated with any accuracy at all when idle skipping
|
||||
is on (the suggested tick rate in that case is much to high in proportion to the actual FPS)
|
||||
2. When dual core is enabled the CommandProcessor allow some elasticity in the FPS/VPS rate. This
|
||||
is especially noticable in Zelda TP who's FPS/VPS for me varies between 0.25 and 0.6 as a
|
||||
result of this.
|
||||
3. PAL 50Hz games: Are 'patched' so that they still run at the correct speed. So if the NTSC 60Hz
|
||||
version has a FPS/VPS of 0.5 the 50Hz game will run at 0.6.
|
||||
*/
|
||||
// ______________________________
|
||||
/**/
|
||||
if (FPS_To_VPS_Rate > 0 && FPS_To_VPS_Rate < ((1.0/3.0 + 1.0/2.0)/2)) FPS_To_VPS_Rate = 1.0/3.0;
|
||||
else if (FPS_To_VPS_Rate > ((1.0/3.0 + 1.0/2.0)/2) && FPS_To_VPS_Rate < ((1.0/2.0 + 1.0/1.0)/2)) FPS_To_VPS_Rate = 1.0/2.0;
|
||||
else FPS_To_VPS_Rate = 1.0;
|
||||
// PAL patch adjustment
|
||||
if (VideoInterface::TargetRefreshRate == 50) FPS_To_VPS_Rate = FPS_To_VPS_Rate * 1.2;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
float TargetFPS = FPS_To_VPS_Rate * (float)VideoInterface::TargetRefreshRate;
|
||||
float FPSPercentage = (FPS / TargetFPS) * 100.0;
|
||||
float VPSPercentage = (VideoInterface::ActualRefreshRate / (float)VideoInterface::TargetRefreshRate) * 100.0;
|
||||
|
||||
// Settings are shown the same for both extended and summary info
|
||||
std::string SSettings = StringFromFormat(" | Core: %s %s",
|
||||
#if defined(JITTEST) && JITTEST
|
||||
#ifdef _M_IX86
|
||||
_CoreParameter.bUseJIT ? "JIT32IL" : "Int32",
|
||||
|
@ -716,17 +779,37 @@ void Callback_VideoCopiedToXFB()
|
|||
_CoreParameter.bUseJIT ? "JIT64" : "Int64",
|
||||
#endif
|
||||
#endif
|
||||
_CoreParameter.bUseDualCore ? "DC" : "SC",
|
||||
_CoreParameter.bUseDualCore ? "DC" : "SC");
|
||||
// Show ~ to indicate that the value may be wrong because the ticks are wrong
|
||||
std::string IdleSkipMessage = "";
|
||||
if (_CoreParameter.bSkipIdle || _CoreParameter.bUseDualCore) IdleSkipMessage = "~";
|
||||
#ifdef EXTENDED_INFO
|
||||
std::string SFPS = StringFromFormat("FPS: %4.1f/%s%2.0f (%s%3.0f%% | %s%1.2f) VPS:%4.0f/%i (%3.0f%%)",
|
||||
FPS, IdleSkipMessage.c_str(), TargetFPS,
|
||||
IdleSkipMessage.c_str(), FPSPercentage, IdleSkipMessage.c_str(), FPS_To_VPS_Rate,
|
||||
VideoInterface::ActualRefreshRate, VideoInterface::TargetRefreshRate, VPSPercentage);
|
||||
std::string STicks = StringFromFormat(" | CPU: %s%i MHz [Real: %i + IdleSkip: %i] / %i MHz (%s%3.0f%%)",
|
||||
IdleSkipMessage.c_str(),
|
||||
(int)(diff),
|
||||
(int)(diff - idleDiff),
|
||||
(int)(idleDiff),
|
||||
SystemTimers::GetTicksPerSecond() / 1000000);
|
||||
SystemTimers::GetTicksPerSecond() / 1000000,
|
||||
IdleSkipMessage.c_str(),
|
||||
TicksPercentage);
|
||||
// Summary information
|
||||
#else
|
||||
std::string SFPS = StringFromFormat("FPS: %4.1f/%s%2.0f (%s%3.0f%%)",
|
||||
FPS, IdleSkipMessage.c_str(), TargetFPS, IdleSkipMessage.c_str(), FPSPercentage);
|
||||
std::string STicks = "";
|
||||
#endif
|
||||
|
||||
std::string SMessage = StringFromFormat("%s%s%s", SFPS.c_str(), SSettings.c_str(), STicks.c_str());
|
||||
|
||||
// Show message
|
||||
if (g_pUpdateFPSDisplay != NULL)
|
||||
g_pUpdateFPSDisplay(temp);
|
||||
|
||||
Host_UpdateStatusBar(temp);
|
||||
|
||||
g_pUpdateFPSDisplay(SMessage.c_str());
|
||||
Host_UpdateStatusBar(SMessage.c_str());
|
||||
// Reset frame counter
|
||||
frames = 0;
|
||||
Timer.Update();
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "CoreTiming.h"
|
||||
#include "StringUtil.h"
|
||||
|
||||
#include <mmsystem.h>
|
||||
|
||||
namespace CoreTiming
|
||||
{
|
||||
|
|
|
@ -641,7 +641,7 @@ void STACKALIGN GatherPipeBursted()
|
|||
}
|
||||
|
||||
|
||||
|
||||
// This is mostly used in single core mode
|
||||
void CatchUpGPU()
|
||||
{
|
||||
// check if we are able to run this buffer
|
||||
|
|
|
@ -258,7 +258,7 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
|||
}
|
||||
|
||||
// SetFinish
|
||||
// THIS IS EXECUTED FROM VIDEO THREAD
|
||||
// THIS IS EXECUTED FROM VIDEO THREAD (BPStructs.cpp) when a new frame has been drawn
|
||||
void SetFinish()
|
||||
{
|
||||
CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
#include "../PluginManager.h"
|
||||
#include "../CoreTiming.h"
|
||||
#include "../HW/SystemTimers.h"
|
||||
#include "StringUtil.h"
|
||||
|
||||
#include <mmsystem.h>
|
||||
|
||||
namespace VideoInterface
|
||||
{
|
||||
|
@ -336,7 +339,7 @@ static u32 LineCount = 0;
|
|||
static u32 LinesPerField = 0;
|
||||
static u64 LastTime = 0;
|
||||
static u32 NextXFBRender = 0;
|
||||
|
||||
int TargetRefreshRate = 0, SyncTicksProgress = 0; float ActualRefreshRate = 0.0;
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
|
@ -965,6 +968,7 @@ void UpdateInterrupts()
|
|||
}
|
||||
}
|
||||
|
||||
// This function is unused
|
||||
void GenerateVIInterrupt(VIInterruptType _VIInterrupt)
|
||||
{
|
||||
switch(_VIInterrupt)
|
||||
|
@ -1001,6 +1005,10 @@ u8* GetXFBPointerBottom()
|
|||
return Memory::GetPointer(m_XFBInfoBottom.FBB);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Screenshot and screen message
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
void UpdateTiming()
|
||||
{
|
||||
switch (m_DisplayControlRegister.FMT)
|
||||
|
@ -1027,9 +1035,42 @@ void UpdateTiming()
|
|||
break;
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Purpose 1: Send VI interrupt for every screen refresh
|
||||
// Purpose 2: Execute XFB copy in homebrew games
|
||||
// Run when: This is run 7200 times per second on full speed
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
void Update()
|
||||
{
|
||||
// -----------------------------------------------------------------------
|
||||
// Calculate actual refresh rate
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
// Update the target refresh rate
|
||||
TargetRefreshRate = (m_DisplayControlRegister.FMT == 0 || m_DisplayControlRegister.FMT == 2)
|
||||
? 60 : 50;
|
||||
|
||||
// Calculate actual refresh rate
|
||||
static u64 LastTick = 0;
|
||||
static int UpdateCheck = timeGetTime() + 1000, TickProgress = 0;
|
||||
if (UpdateCheck < timeGetTime())
|
||||
{
|
||||
UpdateCheck = timeGetTime() + 1000;
|
||||
TickProgress = CoreTiming::GetTicks() - LastTick;
|
||||
// Calculated CPU-GPU synced ticks for the dual core mode too
|
||||
NOTICE_LOG(VIDEO, "Removed: %s Mhz", ThS(SyncTicksProgress / 1000000, false).c_str());
|
||||
SyncTicksProgress += TickProgress;
|
||||
// Multipled by two because of the way TicksPerFrame is calculated (divided by 25 and 30
|
||||
// rather than 50 and 60)
|
||||
ActualRefreshRate = ((float)SyncTicksProgress / (float)TicksPerFrame) * 2.0;
|
||||
LastTick = CoreTiming::GetTicks();
|
||||
SyncTicksProgress = 0;
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// Go through all lines
|
||||
while ((CoreTiming::GetTicks() - LastTime) > (TicksPerFrame / LineCount))
|
||||
{
|
||||
LastTime += (TicksPerFrame / LineCount);
|
||||
|
@ -1101,5 +1142,6 @@ void Update()
|
|||
}
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace VideoInterface
|
|||
|
||||
// Update and draw framebuffer(s)
|
||||
void Update();
|
||||
extern float ActualRefreshRate; extern int TargetRefreshRate, SyncTicksProgress;
|
||||
|
||||
// UpdateInterrupts: check if we have to generate a new VI Interrupt
|
||||
void UpdateInterrupts();
|
||||
|
|
|
@ -160,7 +160,8 @@ void BPWritten(const Bypass& bp)
|
|||
PixelShaderManager::SetDestAlpha(bpmem.dstalpha);
|
||||
break;
|
||||
}
|
||||
case BPMEM_SETDRAWDONE: // This is called when the game is done drawing (eg: like in DX: Begin(); Draw(); End();)
|
||||
// This is called when the game is done drawing the new frame (eg: like in DX: Begin(); Draw(); End();)
|
||||
case BPMEM_SETDRAWDONE:
|
||||
switch (bp.newvalue & 0xFF)
|
||||
{
|
||||
case 0x02:
|
||||
|
|
|
@ -76,26 +76,6 @@ u8* FAKE_GetFifoEndPtr()
|
|||
return &videoBuffer[size];
|
||||
}
|
||||
|
||||
// The loop in EnterLoop sends data through this function.
|
||||
// TODO: Possibly inline it? This one is exported so it will likely not be inlined at all.
|
||||
void Video_SendFifoData(u8* _uData, u32 len)
|
||||
{
|
||||
if (size + len >= FIFO_SIZE)
|
||||
{
|
||||
int pos = (int)(g_pVideoData - videoBuffer);
|
||||
if (size - pos > pos)
|
||||
{
|
||||
PanicAlert("FIFO out of bounds (sz = %i, at %08x)", size, pos);
|
||||
}
|
||||
memmove(&videoBuffer[0], &videoBuffer[pos], size - pos);
|
||||
size -= pos;
|
||||
g_pVideoData = FAKE_GetFifoStartPtr();
|
||||
}
|
||||
memcpy(videoBuffer + size, _uData, len);
|
||||
size += len;
|
||||
OpcodeDecoder_Run();
|
||||
}
|
||||
|
||||
// Executed from another thread, no the graphics thread!
|
||||
// Basically, all it does is set a flag so that the loop will eventually exit, then
|
||||
// waits for the event to be set, which happens when the loop does exit.
|
||||
|
@ -124,7 +104,35 @@ void Fifo_ExitLoopNonBlocking() {
|
|||
fifoStateRun = false;
|
||||
}
|
||||
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Description: Fifo_EnterLoop() sends data through this function.
|
||||
// TODO: Possibly inline it? This one is exported so it will likely not be inlined at all.
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
void Video_SendFifoData(u8* _uData, u32 len)
|
||||
{
|
||||
if (size + len >= FIFO_SIZE)
|
||||
{
|
||||
int pos = (int)(g_pVideoData - videoBuffer);
|
||||
if (size - pos > pos)
|
||||
{
|
||||
PanicAlert("FIFO out of bounds (sz = %i, at %08x)", size, pos);
|
||||
}
|
||||
memmove(&videoBuffer[0], &videoBuffer[pos], size - pos);
|
||||
size -= pos;
|
||||
g_pVideoData = FAKE_GetFifoStartPtr();
|
||||
}
|
||||
// Copy new video instructions to videoBuffer for future use in rendering the new picture
|
||||
memcpy(videoBuffer + size, _uData, len);
|
||||
size += len;
|
||||
OpcodeDecoder_Run();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Description: Main FIFO update loop
|
||||
// Purpose: Keep the Core HW updated about the CPU-GPU distance
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
||||
{
|
||||
fifoStateRun = true;
|
||||
|
@ -160,7 +168,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
|||
video_initialize.pPeekMessages();
|
||||
peek_counter = 0;
|
||||
}
|
||||
// read the data and send it to the VideoPlugin
|
||||
// Create pointer to video data and send it to the VideoPlugin
|
||||
u32 readPtr = _fifo.CPReadPointer;
|
||||
u8 *uData = video_initialize.pGetMemoryPointer(readPtr);
|
||||
|
||||
|
@ -204,6 +212,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
|||
readPtr += distToSend;
|
||||
#endif
|
||||
}
|
||||
// Execute new instructions found in uData
|
||||
Video_SendFifoData(uData, distToSend);
|
||||
Common::SyncInterlockedExchange((LONG*)&_fifo.CPReadPointer, readPtr);
|
||||
Common::SyncInterlockedExchangeAdd((LONG*)&_fifo.CPReadWriteDistance, -distToSend);
|
||||
|
@ -217,3 +226,4 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
|||
fifo_exit_event.SetTimer();
|
||||
#endif
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
@ -379,9 +379,10 @@ void Shutdown(void)
|
|||
OpenGL_Shutdown();
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Enter and exit the video loop
|
||||
// -------------------------------
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
void Video_EnterLoop()
|
||||
{
|
||||
Fifo_EnterLoop(g_VideoInitialize);
|
||||
|
@ -391,13 +392,27 @@ void Video_ExitLoop()
|
|||
{
|
||||
Fifo_ExitLoop();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Screenshot and screen message
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
void Video_Screenshot(const char *_szFilename)
|
||||
{
|
||||
Renderer::SetScreenshot(_szFilename);
|
||||
}
|
||||
|
||||
void Video_AddMessage(const char* pstr, u32 milliseconds)
|
||||
{
|
||||
OSD::AddMessage(pstr, milliseconds);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Run from the CPU thread (from VideoInterface.cpp) for certain homebrew games only
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
void Video_UpdateXFB(u8* _pXFB, u32 _dwWidth, u32 _dwHeight, s32 _dwYOffset, bool scheduling)
|
||||
{
|
||||
if (g_Config.bUseXFB && XFB_isInit())
|
||||
|
@ -422,8 +437,4 @@ void Video_UpdateXFB(u8* _pXFB, u32 _dwWidth, u32 _dwHeight, s32 _dwYOffset, boo
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Video_AddMessage(const char* pstr, u32 milliseconds)
|
||||
{
|
||||
OSD::AddMessage(pstr, milliseconds);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue