PCSX2-Counters: Move VideoMode init code from _gsSMODEwrite to SYSCALL

* Moving the code to SYSCALL enables us to detect all the video modes properly.
* Added proper detection of VESA,HDTV,BIOS video modes.
This commit is contained in:
Akash 2016-07-01 17:07:55 +05:30
parent e7d4bc4506
commit 78bf5ad88e
4 changed files with 113 additions and 57 deletions

View File

@ -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;
@ -211,7 +218,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, Fixed100 framesPerSecond, u32 s
u64 hBlank = Scanline / 2;
u64 hRender = Scanline - hBlank;
if (gsVideoMode == GS_VideoMode::PROGRESSIVE)
if (!IsAnalogVideoMode())
{
hBlank /= 2;
hRender /= 2;
@ -233,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 (gsVideoMode != GS_VideoMode::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);
@ -246,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()
{
@ -259,35 +282,64 @@ u32 UpdateVSyncRate()
u32 scanlines = 0;
bool isCustom = false;
if(gsVideoMode == GS_VideoMode::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 (gsVideoMode == GS_VideoMode::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 (gsVideoMode == GS_VideoMode::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");
}
bool ActiveVideoMode = gsVideoMode != GS_VideoMode::Uninitialized;
if (vSyncInfo.Framerate != framerate || vSyncInfo.VideoMode != gsVideoMode)
{
vSyncInfo.VideoMode = gsVideoMode;
vSyncInfoCalc( &vSyncInfo, framerate, scanlines );
Console.WriteLn( Color_Green, "(UpdateVSyncRate) Mode Changed to %s.", (gsVideoMode == GS_VideoMode::PAL ) ? "PAL" :
(gsVideoMode == GS_VideoMode::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
@ -306,6 +358,7 @@ u32 UpdateVSyncRate()
{
m_iTicks = ticks;
gsOnModeChanged( vSyncInfo.Framerate, m_iTicks );
if (ActiveVideoMode)
Console.WriteLn( Color_Green, "(UpdateVSyncRate) FPS Limit Changed : %.02f fps", fpslimit.ToFloat()*2 );
}

View File

@ -33,7 +33,6 @@ void gsOnModeChanged( Fixed100 framerate, u32 newTickrate )
}
bool gsIsInterlaced = false;
GS_VideoMode gsVideoMode = GS_VideoMode::NTSC;
void gsSetVideoMode(GS_VideoMode mode )
@ -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 )
gsSetVideoMode( GS_VideoMode::PAL );
else if (value & 0x400000 || value & 0x200000)
gsSetVideoMode( GS_VideoMode::PROGRESSIVE );
else
gsSetVideoMode( GS_VideoMode::NTSC );
break;
case GS_SMODE2:
if(mem == GS_SMODE2)
gsIsInterlaced = (value & 0x1);
break;
}
}
//////////////////////////////////////////////////////////////////////////

View File

@ -219,9 +219,17 @@ struct GSRegSIGBLID
enum class GS_VideoMode : int
{
Uninitialized,
Unknown,
NTSC,
PAL,
PROGRESSIVE
VESA,
HDTV_480P,
HDTV_576P,
HDTV_720P,
HDTV_1080I,
HDTV_1080P,
BIOS
};
extern GS_VideoMode gsVideoMode;

View File

@ -22,7 +22,9 @@
#include "R5900.h"
#include "R5900OpcodeTables.h"
#include "R5900Exceptions.h"
#include "GS.h"
GS_VideoMode gsVideoMode = GS_VideoMode::Uninitialized;
static __fi bool _add64_Overflow( s64 x, s64 y, s64 &ret )
{
@ -886,40 +888,47 @@ void SYSCALL()
const char* field = (cpuRegs.GPR.n.a2.UL[0] & 1) ? "FRAME" : "FIELD";
std::string mode;
// Warning info might be incorrect!
switch (cpuRegs.GPR.n.a1.UC[0]) {
case 0x2: mode = "NTSC 640x448 @ 59.940 (59.82)"; break;
switch (cpuRegs.GPR.n.a1.UC[0])
{
case 0x0:
case 0x2:
mode = "NTSC 640x448 @ 59.940 (59.82)"; gsSetVideoMode(GS_VideoMode::NTSC); break;
case 0x3: mode = "PAL 640x512 @ 50.000 (49.76)"; break;
case 0x1:
case 0x3:
mode = "PAL 640x512 @ 50.000 (49.76)"; gsSetVideoMode(GS_VideoMode::PAL); break;
case 0x1A: mode = "VESA 640x480 @ 59.940"; break;
case 0x1B: mode = "VESA 640x480 @ 72.809"; break;
case 0x1C: mode = "VESA 640x480 @ 75.000"; break;
case 0x1D: mode = "VESA 640x480 @ 85.008"; break;
case 0x1A: mode = "VESA 640x480 @ 59.940"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x1B: mode = "VESA 640x480 @ 72.809"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x1C: mode = "VESA 640x480 @ 75.000"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x1D: mode = "VESA 640x480 @ 85.008"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x2A: mode = "VESA 800x600 @ 56.250"; break;
case 0x2B: mode = "VESA 800x600 @ 60.317"; break;
case 0x2C: mode = "VESA 800x600 @ 72.188"; break;
case 0x2D: mode = "VESA 800x600 @ 75.000"; break;
case 0x2E: mode = "VESA 800x600 @ 85.061"; break;
case 0x2A: mode = "VESA 800x600 @ 56.250"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x2B: mode = "VESA 800x600 @ 60.317"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x2C: mode = "VESA 800x600 @ 72.188"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x2D: mode = "VESA 800x600 @ 75.000"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x2E: mode = "VESA 800x600 @ 85.061"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x3B: mode = "VESA 1024x768 @ 60.004"; break;
case 0x3C: mode = "VESA 1024x768 @ 70.069"; break;
case 0x3D: mode = "VESA 1024x768 @ 75.029"; break;
case 0x3E: mode = "VESA 1024x768 @ 84.997"; break;
case 0x3B: mode = "VESA 1024x768 @ 60.004"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x3C: mode = "VESA 1024x768 @ 70.069"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x3D: mode = "VESA 1024x768 @ 75.029"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x3E: mode = "VESA 1024x768 @ 84.997"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x4A: mode = "VESA 1280x1024 @ 63.981"; break;
case 0x4B: mode = "VESA 1280x1024 @ 79.976"; break;
case 0x4A: mode = "VESA 1280x1024 @ 63.981"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x4B: mode = "VESA 1280x1024 @ 79.976"; gsSetVideoMode(GS_VideoMode::VESA); break;
case 0x50: mode = "HDTV 720x480 @ 59.94"; break;
case 0x51: mode = "HDTV 1920x1080 @ 60.00"; break;
case 0x52: mode = "HDTV 1280x720 @ ??.???"; break;
case 0x53: mode = "HDTV 768x576 @ ??.???"; break;
case 0x54: mode = "HDTV 1920x1080 @ ??.???"; break;
case 0x50: mode = "HDTV 720x480 @ 59.94"; gsSetVideoMode(GS_VideoMode::HDTV_480P); break;
case 0x51: mode = "HDTV 1920x1080 @ 60.00"; gsSetVideoMode(GS_VideoMode::HDTV_1080I); break;
case 0x52: mode = "HDTV 1280x720 @ ??.???"; gsSetVideoMode(GS_VideoMode::HDTV_720P); break;
case 0x53: mode = "HDTV 768x576 @ ??.???"; gsSetVideoMode(GS_VideoMode::HDTV_576P); break;
case 0x54: mode = "HDTV 1920x1080 @ ??.???"; gsSetVideoMode(GS_VideoMode::HDTV_1080P); break;
case 0x72: mode = "DVD NTSC 640x448 @ ??.???"; break;
case 0x73: mode = "DVD PAL/480P 720x480 @ ??.???"; break;
case 0x72: mode = "DVD NTSC 640x448 @ ??.???"; gsSetVideoMode(GS_VideoMode::BIOS); break;
case 0x73: mode = "DVD PAL 720x480 @ ??.???"; gsSetVideoMode(GS_VideoMode::BIOS); break;
default: Console.Error("Mode %x is not supported. Report me upstream", cpuRegs.GPR.n.a1.UC[0]);
default:
Console.Error("Mode %x is not supported. Report me upstream", cpuRegs.GPR.n.a1.UC[0]);
gsSetVideoMode(GS_VideoMode::Unknown);
}
Console.Warning("Set GS CRTC configuration. Interlace %s. Field Type %s. Mode %s", inter, field, mode.c_str());
}