From 78bf5ad88e9fc5223150f6ba7aa46c5f48cc3388 Mon Sep 17 00:00:00 2001 From: Akash Date: Fri, 1 Jul 2016 17:07:55 +0530 Subject: [PATCH] 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. --- pcsx2/Counters.cpp | 83 ++++++++++++++++++++++++++++++++------- pcsx2/GS.cpp | 16 +------- pcsx2/GS.h | 10 ++++- pcsx2/R5900OpcodeImpl.cpp | 61 ++++++++++++++++------------ 4 files changed, 113 insertions(+), 57 deletions(-) diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp index d54f2afb65..feabd7ec62 100644 --- a/pcsx2/Counters.cpp +++ b/pcsx2/Counters.cpp @@ -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,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(); diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index f1c35d0b9c..a6a210c0ff 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -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; - } } ////////////////////////////////////////////////////////////////////////// diff --git a/pcsx2/GS.h b/pcsx2/GS.h index 62e2fdafbb..47b5867fd1 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -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; diff --git a/pcsx2/R5900OpcodeImpl.cpp b/pcsx2/R5900OpcodeImpl.cpp index 8e0fb36fdd..af89d2358a 100644 --- a/pcsx2/R5900OpcodeImpl.cpp +++ b/pcsx2/R5900OpcodeImpl.cpp @@ -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()); }