Skip to content

Commit

Permalink
Merge pull request #1442 from ssakash/Counters
Browse files Browse the repository at this point in the history
PCSX2-Counters: Improve video mode detection
  • Loading branch information
ramapcsx2 committed Jul 18, 2016
2 parents e680a90 + 2ed67f6 commit ddc6862
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 97 deletions.
4 changes: 2 additions & 2 deletions pcsx2/CDVD/CDVD.cpp
Expand Up @@ -25,7 +25,7 @@
#include "CDVD_internal.h"
#include "CDVDisoReader.h"

#include "GS.h" // for gsRegionMode
#include "GS.h" // for gsVideoMode
#include "Elfheader.h"
#include "ps2/BiosTools.h"
#include "GameDatabase.h"
Expand Down Expand Up @@ -958,7 +958,7 @@ u8 monthmap[13] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

void cdvdVsync() {
cdvd.RTCcount++;
if (cdvd.RTCcount < ((gsRegionMode == Region_NTSC) ? 60 : 50)) return;
if (cdvd.RTCcount < ((gsVideoMode == GS_VideoMode::NTSC) ? 60 : 50)) return;
cdvd.RTCcount = 0;

if ( cdvd.Status == CDVD_STATUS_TRAY_OPEN )
Expand Down
6 changes: 0 additions & 6 deletions pcsx2/Config.h
Expand Up @@ -288,11 +288,6 @@ struct Pcsx2Config
bool FrameSkipEnable;
bool VsyncEnable;

// The region mode controls the default Maximum/Minimum FPS settings and also
// regulates the vsync rates (which in turn control the IOP's SPU2 tick sync and ensure
// proper audio playback speed).
int DefaultRegionMode; // 0=NTSC and 1=PAL

int FramesToDraw; // number of consecutive frames (fields) to render
int FramesToSkip; // number of consecutive frames (fields) to skip

Expand All @@ -318,7 +313,6 @@ struct Pcsx2Config
OpEqu( FramerateNTSC ) &&
OpEqu( FrameratePAL ) &&

OpEqu( DefaultRegionMode ) &&
OpEqu( FramesToDraw ) &&
OpEqu( FramesToSkip );
}
Expand Down
92 changes: 71 additions & 21 deletions pcsx2/Counters.cpp
Expand Up @@ -58,6 +58,13 @@ static void rcntWmode(int index, u32 value);
static void rcntWtarget(int index, u32 value);
static void rcntWhold(int index, u32 value);

static bool IsAnalogVideoMode()
{
if (gsVideoMode == GS_VideoMode::PAL || gsVideoMode == GS_VideoMode::NTSC)
return true;

return false;
}

void rcntReset(int index) {
counters[index].count = 0;
Expand Down Expand Up @@ -155,9 +162,6 @@ void rcntInit()
vsyncCounter.Mode = MODE_VRENDER;
vsyncCounter.sCycle = cpuRegs.cycle;

// Set the video mode to user's default request:
gsSetRegionMode( (GS_RegionMode)EmuConfig.GS.DefaultRegionMode );

for (i=0; i<4; i++) rcntReset(i);
cpuRcntSet();
}
Expand All @@ -173,7 +177,7 @@ static u64 m_iStart=0;
struct vSyncTimingInfo
{
Fixed100 Framerate; // frames per second (8 bit fixed)
GS_RegionMode RegionMode; // used to detect change (interlaced/progressive)
GS_VideoMode VideoMode; // used to detect change (interlaced/progressive)
u32 Render; // time from vblank end to vblank start (cycles)
u32 Blank; // time from vblank start to vblank end (cycles)

Expand Down Expand Up @@ -214,7 +218,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, Fixed100 framesPerSecond, u32 s
u64 hBlank = Scanline / 2;
u64 hRender = Scanline - hBlank;

if (gsRegionMode == Region_NTSC_PROGRESSIVE)
if (!IsAnalogVideoMode())
{
hBlank /= 2;
hRender /= 2;
Expand All @@ -236,7 +240,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, Fixed100 framesPerSecond, u32 s
else if ((hBlank - info->hBlank) >= 5000) info->hBlank++;

// Calculate accumulative hSync rounding error per half-frame:
if (gsRegionMode != Region_NTSC_PROGRESSIVE) // gets off the chart in that mode
if (IsAnalogVideoMode()) // gets off the chart in that mode
{
u32 hSyncCycles = ((info->hRender + info->hBlank) * scansPerFrame) / 2;
u32 vSyncCycles = (info->Render + info->Blank);
Expand All @@ -249,6 +253,22 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, Fixed100 framesPerSecond, u32 s
// is thus not worth the effort at this time.
}

static const char* ReportVideoMode()
{
switch (gsVideoMode)
{
case GS_VideoMode::PAL: return "PAL";
case GS_VideoMode::NTSC: return "NTSC";
case GS_VideoMode::VESA: return "VESA";
case GS_VideoMode::BIOS: return "BIOS";
case GS_VideoMode::HDTV_480P: return "HDTV 480p";
case GS_VideoMode::HDTV_576P: return "HDTV 576p";
case GS_VideoMode::HDTV_720P: return "HDTV 720p";
case GS_VideoMode::HDTV_1080I: return "HDTV 1080i";
case GS_VideoMode::HDTV_1080P: return "HDTV 1080p";
default: return "Unknown";
}
}

u32 UpdateVSyncRate()
{
Expand All @@ -262,35 +282,64 @@ u32 UpdateVSyncRate()
u32 scanlines = 0;
bool isCustom = false;

if( gsRegionMode == Region_PAL )
//Set up scanlines and framerate based on video mode
switch (gsVideoMode)
{
case GS_VideoMode::Uninitialized: // SYSCALL instruction hasn't executed yet, give some temporary values.
framerate = 60;
scanlines = SCANLINES_TOTAL_NTSC;
break;

case GS_VideoMode::PAL:
isCustom = (EmuConfig.GS.FrameratePAL != 50.0);
framerate = EmuConfig.GS.FrameratePAL / 2;
scanlines = SCANLINES_TOTAL_PAL;
if (!gsIsInterlaced) scanlines += 3;
}
else if ( gsRegionMode == Region_NTSC )
{
break;

case GS_VideoMode::NTSC:
isCustom = (EmuConfig.GS.FramerateNTSC != 59.94);
framerate = EmuConfig.GS.FramerateNTSC / 2;
scanlines = SCANLINES_TOTAL_NTSC;
if (!gsIsInterlaced) scanlines += 1;
}
else if ( gsRegionMode == Region_NTSC_PROGRESSIVE )
{
isCustom = (EmuConfig.GS.FramerateNTSC != 59.94);
framerate = EmuConfig.GS.FramerateNTSC / 2;
break;

case GS_VideoMode::HDTV_480P:
framerate = 29.97;
scanlines = SCANLINES_TOTAL_NTSC;
break;

case GS_VideoMode::HDTV_1080P:
case GS_VideoMode::HDTV_1080I:
case GS_VideoMode::HDTV_576P:
case GS_VideoMode::HDTV_720P:
case GS_VideoMode::VESA:
case GS_VideoMode::BIOS:
framerate = 30;
scanlines = SCANLINES_TOTAL_NTSC;
break;

// Falls through to unknown when unidentified mode parameter of SetGsCrt is detected.
case GS_VideoMode::Unknown:
// For Release builds, keep using the NTSC timing values when unknown video mode is detected.
// Assert will be triggered for debug/dev builds.
framerate = FRAMERATE_NTSC;
scanlines = SCANLINES_TOTAL_NTSC;
Console.Error("PCSX2-Counters: Unknown video mode detected");

default:
pxAssertDev(false , "Unknown video mode detected via SetGsCrt");
}

if (vSyncInfo.Framerate != framerate || vSyncInfo.RegionMode != gsRegionMode)
bool ActiveVideoMode = gsVideoMode != GS_VideoMode::Uninitialized;
if (vSyncInfo.Framerate != framerate || vSyncInfo.VideoMode != gsVideoMode)
{
vSyncInfo.RegionMode = gsRegionMode;
vSyncInfo.VideoMode = gsVideoMode;
vSyncInfoCalc( &vSyncInfo, framerate, scanlines );
Console.WriteLn( Color_Green, "(UpdateVSyncRate) Mode Changed to %s.", ( gsRegionMode == Region_PAL ) ? "PAL" :
( gsRegionMode == Region_NTSC ) ? "NTSC" : "NTSC Progressive Scan" );
if(ActiveVideoMode)
Console.WriteLn( Color_Green, "(UpdateVSyncRate) Mode Changed to %s.", ReportVideoMode());

if( isCustom )
if( isCustom && ActiveVideoMode)
Console.Indent().WriteLn( Color_StrongGreen, "... with user configured refresh rate: %.02f Hz", 2 * framerate.ToFloat() );

hsyncCounter.CycleT = vSyncInfo.hRender; // Amount of cycles before the counter will be updated
Expand All @@ -309,7 +358,8 @@ u32 UpdateVSyncRate()
{
m_iTicks = ticks;
gsOnModeChanged( vSyncInfo.Framerate, m_iTicks );
Console.WriteLn( Color_Green, "(UpdateVSyncRate) FPS Limit Changed : %.02f fps", fpslimit.ToFloat()*2 );
if (ActiveVideoMode)
Console.WriteLn( Color_Green, "(UpdateVSyncRate) FPS Limit Changed : %.02f fps", fpslimit.ToFloat()*2 );
}

m_iStart = GetCPUTicks();
Expand Down
26 changes: 6 additions & 20 deletions pcsx2/GS.cpp
Expand Up @@ -32,15 +32,14 @@ void gsOnModeChanged( Fixed100 framerate, u32 newTickrate )
GetMTGS().SendSimplePacket( GS_RINGTYPE_MODECHANGE, framerate.Raw, newTickrate, 0 );
}

bool gsIsInterlaced = false;
GS_RegionMode gsRegionMode = Region_NTSC;
bool gsIsInterlaced = false;


void gsSetRegionMode( GS_RegionMode region )
void gsSetVideoMode(GS_VideoMode mode )
{
if( gsRegionMode == region ) return;
if( gsVideoMode == mode ) return;

gsRegionMode = region;
gsVideoMode = mode;
UpdateVSyncRate();
}

Expand Down Expand Up @@ -157,21 +156,8 @@ __fi void gsWrite8(u32 mem, u8 value)

static void _gsSMODEwrite( u32 mem, u32 value )
{
switch (mem)
{
case GS_SMODE1:
if ( (value & 0x6000) == 0x6000 )
gsSetRegionMode( Region_PAL );
else if (value & 0x400000 || value & 0x200000)
gsSetRegionMode( Region_NTSC_PROGRESSIVE );
else
gsSetRegionMode( Region_NTSC );
break;

case GS_SMODE2:
if(mem == GS_SMODE2)
gsIsInterlaced = (value & 0x1);
break;
}
}

//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -436,5 +422,5 @@ void gsResetFrameSkip()
void SaveStateBase::gsFreeze()
{
FreezeMem(PS2MEM_GS, 0x2000);
Freeze(gsRegionMode);
Freeze(gsVideoMode);
}
20 changes: 14 additions & 6 deletions pcsx2/GS.h
Expand Up @@ -217,14 +217,22 @@ struct GSRegSIGBLID
#define GSIMR ((u32&)*(PS2MEM_GS+0x1010))
#define GSSIGLBLID ((GSRegSIGBLID&)*(PS2MEM_GS+0x1080))

enum GS_RegionMode
enum class GS_VideoMode : int
{
Region_NTSC,
Region_PAL,
Region_NTSC_PROGRESSIVE
Uninitialized,
Unknown,
NTSC,
PAL,
VESA,
HDTV_480P,
HDTV_576P,
HDTV_720P,
HDTV_1080I,
HDTV_1080P,
BIOS
};

extern GS_RegionMode gsRegionMode;
extern GS_VideoMode gsVideoMode;

/////////////////////////////////////////////////////////////////////////////
// MTGS Threaded Class Declaration
Expand Down Expand Up @@ -363,7 +371,7 @@ extern s32 gsOpen();
extern void gsClose();
extern void gsReset();
extern void gsOnModeChanged( Fixed100 framerate, u32 newTickrate );
extern void gsSetRegionMode( GS_RegionMode isPal );
extern void gsSetVideoMode( GS_VideoMode mode );
extern void gsResetFrameSkip();
extern void gsPostVsyncStart();
extern void gsFrameSkip();
Expand Down
5 changes: 0 additions & 5 deletions pcsx2/Pcsx2Config.cpp
Expand Up @@ -206,7 +206,6 @@ Pcsx2Config::GSOptions::GSOptions()
DisableOutput = false;
VsyncQueueSize = 2;

DefaultRegionMode = Region_NTSC;
FramesToDraw = 2;
FramesToSkip = 2;

Expand All @@ -231,10 +230,6 @@ void Pcsx2Config::GSOptions::LoadSave( IniInterface& ini )
IniEntry( FramerateNTSC );
IniEntry( FrameratePAL );

// WARNING: array must be NULL terminated to compute it size
static const wxChar * const ntsc_pal_str[3] = { L"ntsc", L"pal", NULL };
ini.EnumEntry( L"DefaultRegionMode", DefaultRegionMode, ntsc_pal_str, DefaultRegionMode );

IniEntry( FramesToDraw );
IniEntry( FramesToSkip );
}
Expand Down

0 comments on commit ddc6862

Please sign in to comment.