diff --git a/common/build/Utilities/utilities.vcproj b/common/build/Utilities/utilities.vcproj
index 1c15365662..0c70dc5300 100644
--- a/common/build/Utilities/utilities.vcproj
+++ b/common/build/Utilities/utilities.vcproj
@@ -465,6 +465,10 @@
RelativePath="..\..\include\Utilities\Exceptions.h"
>
+
+
diff --git a/common/include/PS2Edefs.h b/common/include/PS2Edefs.h
index 8e8b0b69d1..8fa72bfb94 100644
--- a/common/include/PS2Edefs.h
+++ b/common/include/PS2Edefs.h
@@ -527,6 +527,7 @@ typedef void (CALLBACK* _GSsetBaseMem)(void*);
typedef void (CALLBACK* _GSsetGameCRC)(int, int);
typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip);
typedef void (CALLBACK* _GSsetFrameLimit)(int limit);
+typedef void (CALLBACK* _GSsetVsync)(int enabled);
typedef int (CALLBACK* _GSsetupRecording)(int, void*);
typedef void (CALLBACK* _GSreset)();
typedef void (CALLBACK* _GSwriteCSR)(u32 value);
@@ -534,8 +535,8 @@ typedef void (CALLBACK* _GSmakeSnapshot)(const char *path);
typedef void (CALLBACK* _GSmakeSnapshot2)(const char *path, int*, int);
// Worthless crap function that returns GS plugin specific data via some
-// undocumented void* to a struct. If ant pad plugin actually relies on
-// this info, it deserves to fail new nwer pcsx2s. -- air
+// undocumented void* to a struct. If any pad plugin actually relies on
+// this info, it deserves to fail new newer pcsx2s. -- air
//typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info);
// PAD
@@ -673,17 +674,18 @@ extern _GSreadFIFO GSreadFIFO;
extern _GSreadFIFO2 GSreadFIFO2;
extern _GSchangeSaveState GSchangeSaveState;
-extern _GSmakeSnapshot GSmakeSnapshot;
+extern _GSmakeSnapshot GSmakeSnapshot;
extern _GSmakeSnapshot2 GSmakeSnapshot2;
-extern _GSirqCallback GSirqCallback;
-extern _GSprintf GSprintf;
-extern _GSsetBaseMem GSsetBaseMem;
-extern _GSsetGameCRC GSsetGameCRC;
-extern _GSsetFrameSkip GSsetFrameSkip;
-extern _GSsetFrameLimit GSsetFrameLimit;
-extern _GSsetupRecording GSsetupRecording;
-extern _GSreset GSreset;
-extern _GSwriteCSR GSwriteCSR;
+extern _GSirqCallback GSirqCallback;
+extern _GSprintf GSprintf;
+extern _GSsetBaseMem GSsetBaseMem;
+extern _GSsetGameCRC GSsetGameCRC;
+extern _GSsetFrameSkip GSsetFrameSkip;
+extern _GSsetFrameLimit GSsetFrameLimit;
+extern _GSsetVsync GSsetVsync;
+extern _GSsetupRecording GSsetupRecording;
+extern _GSreset GSreset;
+extern _GSwriteCSR GSwriteCSR;
// PAD
extern _PADopen PADopen;
diff --git a/common/include/Utilities/Dependencies.h b/common/include/Utilities/Dependencies.h
index 7753b886e8..6d752108f8 100644
--- a/common/include/Utilities/Dependencies.h
+++ b/common/include/Utilities/Dependencies.h
@@ -17,8 +17,12 @@
// Dependencies.h : Contains classes required by all Utilities headers.
-//////////////////////////////////////////////////////////////////////////////////////////
-// DeclareNoncopyableObject
+// This should prove useful....
+#define wxsFormat wxString::Format
+
+// --------------------------------------------------------------------------------------
+// DeclareNoncopyableObject
+// --------------------------------------------------------------------------------------
// This macro provides an easy and clean method for ensuring objects are not copyable.
// Simply add the macro to the head or tail of your class declaration, and attempts to
// copy the class will give you a moderately obtuse compiler error that will have you
diff --git a/common/include/Utilities/FixedPointTypes.h b/common/include/Utilities/FixedPointTypes.h
new file mode 100644
index 0000000000..5457df05c7
--- /dev/null
+++ b/common/include/Utilities/FixedPointTypes.h
@@ -0,0 +1,210 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#pragma once
+
+#include "Dependencies.h"
+
+template< int Precision >
+struct FixedInt
+{
+ s32 Raw;
+
+ FixedInt()
+ {
+ Raw = 0;
+ }
+
+ FixedInt( int signedval )
+ {
+ Raw = signedval * Precision;
+ }
+
+ FixedInt( double doubval )
+ {
+ Raw = (int)(doubval * (double)Precision);
+ }
+
+ FixedInt( float floval )
+ {
+ Raw = (int)(floval * (float)Precision);
+ }
+
+ bool operator ==( const FixedInt& right ) const
+ {
+ return Raw == right.Raw;
+ }
+
+ bool operator !=( const FixedInt& right ) const
+ {
+ return Raw != right.Raw;
+ }
+
+ FixedInt operator+( const FixedInt& right ) const
+ {
+ return FixedInt().SetRaw( Raw + right.Raw );
+ }
+
+ FixedInt operator-( const FixedInt& right ) const
+ {
+ return FixedInt().SetRaw( Raw + right.Raw );
+ }
+
+ FixedInt& operator+=( const FixedInt& right )
+ {
+ return SetRaw( Raw + right.Raw );
+ }
+
+ FixedInt& operator-=( const FixedInt& right )
+ {
+ return SetRaw( Raw + right.Raw );
+ }
+
+ bool operator>( const FixedInt& right ) const { return Raw > right.Raw; }
+ bool operator>=( const FixedInt& right ) const { return Raw >= right.Raw; }
+ bool operator<( const FixedInt& right ) const { return Raw < right.Raw; }
+ bool operator<=( const FixedInt& right ) const { return Raw <= right.Raw; }
+
+ FixedInt& ConfineTo( const FixedInt& low, const FixedInt& high )
+ {
+ return SetRaw( std::min( std::max( Raw, low.Raw ), high.Raw ) );
+ }
+
+ // Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
+ // you'll need to use the Raw values directly.
+ FixedInt operator*( const FixedInt& right ) const
+ {
+ s64 mulres = (s64)Raw * right.Raw;
+ return FixedInt().SetRaw( (s32)(mulres / Precision) );
+ }
+
+ // Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
+ // you'll need to use the Raw values directly.
+ FixedInt operator/( const FixedInt& right ) const
+ {
+ s64 divres = Raw * Precision;
+ return FixedInt().SetRaw( (s32)(divres / right.Raw) );
+ }
+
+ // Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
+ // you'll need to use the Raw values directly.
+ FixedInt& operator*=( const FixedInt& right )
+ {
+ s64 mulres = (s64)Raw * right.Raw;
+ return SetRaw( (s32)(mulres / Precision) );
+ }
+
+ // Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
+ // you'll need to use the Raw values directly.
+ FixedInt& operator/=( const FixedInt& right )
+ {
+ s64 divres = Raw * Precision;
+ return SetRaw( (s32)(divres / right.Raw) );
+ }
+
+ // returns TRUE if the value overflows the legal integer range of this container.
+ static bool OverflowCheck( int signedval )
+ {
+ return ( signedval >= (INT_MAX / Precision) );
+ }
+
+ // returns TRUE if the value overflows the legal integer range of this container.
+ static bool OverflowCheck( double signedval )
+ {
+ return ( signedval >= (INT_MAX / Precision) );
+ }
+
+ int GetWhole() const { return Raw / Precision; }
+ int GetFraction() const { return Raw % Precision; }
+
+ FixedInt& SetRaw( s32 rawsrc )
+ {
+ Raw = rawsrc;
+ return *this;
+ }
+
+ FixedInt& Round()
+ {
+ Raw = ToIntRounded();
+ return *this;
+ }
+
+ FixedInt& SetWhole( s32 wholepart )
+ {
+ pxAssert( wholepart < (INT_MAX / Precision) );
+ Raw = GetFraction() + (wholepart * Precision);
+ return *this;
+ }
+
+ FixedInt& SetFraction( u32 fracpart )
+ {
+ Raw = (GetWhole() * Precision) + fracpart;
+ return *this;
+ }
+
+ wxString ToString() const
+ {
+ return wxsFormat( L"%d.%d", GetWhole(), (GetFraction() * 100) / Precision );
+ }
+
+ wxString ToString( int fracDigits ) const
+ {
+ if( fracDigits == 0 ) return wxsFormat( L"%d", GetWhole() );
+
+ pxAssert( fracDigits <= 7 ); // higher numbers would just cause overflows and bad mojo.
+ int mulby = (int)pow( 10.0, fracDigits );
+ return wxsFormat( L"%d.%d", GetWhole(), (GetFraction() * mulby) / Precision );
+ }
+
+ double ToDouble() const
+ {
+ return ((double)Raw / (double)Precision);
+ }
+
+ float ToFloat() const
+ {
+ return ((float)Raw / (float)Precision);
+ }
+
+ int ToIntTruncated() const
+ {
+ return Raw / Precision;
+ }
+
+ int ToIntRounded() const
+ {
+ return (Raw + (Precision/2)) / Precision;
+ }
+
+ static FixedInt FromString( const wxString parseFrom, const FixedInt& defval )
+ {
+ long whole, frac;
+ wxString afterFirst( parseFrom.AfterFirst( L'.' ).Mid(0, 5) );
+ if( !parseFrom.BeforeFirst( L'.' ).ToLong( &whole ) || !afterFirst.ToLong( &frac ) )
+ return defval;
+
+ FixedInt retval( whole );
+
+ if( afterFirst.Length() != 0 && frac != 0 )
+ {
+ int fracPower = (int)pow( 10.0, (int)afterFirst.Length() );
+ retval.SetFraction( (frac * Precision) / fracPower );
+ }
+ return retval;
+ }
+};
+
+typedef FixedInt<256> Fixed256;
+typedef FixedInt<100> Fixed100;
diff --git a/common/include/Utilities/StringHelpers.h b/common/include/Utilities/StringHelpers.h
index 9ecb466e1b..8a3a835aab 100644
--- a/common/include/Utilities/StringHelpers.h
+++ b/common/include/Utilities/StringHelpers.h
@@ -17,7 +17,6 @@
#include "Dependencies.h"
-#include
#include
#include // for wxPoint/wxRect stuff
@@ -29,9 +28,6 @@ extern wxString fromAscii( const char* src );
// wxWidgets lacks one of its own...
extern const wxRect wxDefaultRect;
-// This should prove useful....
-#define wxsFormat wxString::Format
-
extern void SplitString( wxArrayString& dest, const wxString& src, const wxString& delims, wxStringTokenizerMode mode = wxTOKEN_RET_EMPTY_ALL );
extern void JoinString( wxString& dest, const wxArrayString& src, const wxString& separator );
diff --git a/pcsx2/Common.h b/pcsx2/Common.h
index 13532db030..46b820af42 100644
--- a/pcsx2/Common.h
+++ b/pcsx2/Common.h
@@ -28,7 +28,6 @@
static const u32 BIAS = 2; // Bus is half of the actual ps2 speed
static const u32 PS2CLK = 294912000; //hz /* 294.912 mhz */
-//#define PS2CLK 36864000 /* 294.912 mhz */
static const ConsoleColors ConColor_IOP = Color_Yellow;
static const ConsoleColors ConColor_EE = Color_Cyan;
diff --git a/pcsx2/Config.h b/pcsx2/Config.h
index cfb8e37dad..5cd12f83f4 100644
--- a/pcsx2/Config.h
+++ b/pcsx2/Config.h
@@ -258,6 +258,16 @@ struct ConsoleLogFilters
ConsoleLogFilters();
void LoadSave( IniInterface& ini );
+
+ bool operator ==( const ConsoleLogFilters& right ) const
+ {
+ return OpEqu( bitset );
+ }
+
+ bool operator !=( const ConsoleLogFilters& right ) const
+ {
+ return !this->operator ==( right );
+ }
};
// --------------------------------------------------------------------------------------
@@ -371,43 +381,49 @@ struct Pcsx2Config
};
// ------------------------------------------------------------------------
- struct VideoOptions
+ struct GSOptions
{
// forces the MTGS to execute tags/tasks in fully blocking/synchronous
// style. Useful for debugging potential bugs in the MTGS pipeline.
- bool SynchronousMTGS;
-
- bool EnableFrameLimiting;
- bool EnableFrameSkipping;
+ bool SynchronousMTGS;
+ bool FrameLimitEnable;
+ 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 DefaultRegionMode; // 0=NTSC and 1=PAL
- int FpsTurbo; // Limiting kicks in if fps goes beyond this (turbo enabled)
- int FpsLimit; // Limiting kicks in if fps goes beyond this line
- int FpsSkip; // Skipping kicks in if fps drops below this line
- int ConsecutiveFrames; // number of consecutive frames (fields) to render
- int ConsecutiveSkip; // number of consecutive frames (fields) to skip
+ int ConsecutiveFrames; // number of consecutive frames (fields) to render
+ int ConsecutiveSkip; // number of consecutive frames (fields) to skip
- VideoOptions();
+ Fixed100 LimitScalar;
+ Fixed100 FramerateNTSC;
+ Fixed100 FrameratePAL;
+
+ GSOptions();
void LoadSave( IniInterface& conf );
- bool operator ==( const VideoOptions& right ) const
+ bool operator ==( const GSOptions& right ) const
{
return
- OpEqu( EnableFrameSkipping ) &&
- OpEqu( EnableFrameLimiting ) &&
+ OpEqu( SynchronousMTGS ) &&
+ OpEqu( FrameSkipEnable ) &&
+ OpEqu( FrameLimitEnable ) &&
+ OpEqu( VsyncEnable ) &&
+
+ OpEqu( LimitScalar ) &&
+ OpEqu( FramerateNTSC ) &&
+ OpEqu( FrameratePAL ) &&
+
OpEqu( DefaultRegionMode ) &&
- OpEqu( FpsTurbo ) &&
- OpEqu( FpsLimit ) &&
- OpEqu( FpsSkip ) &&
OpEqu( ConsecutiveFrames ) &&
OpEqu( ConsecutiveSkip );
}
- bool operator !=( const VideoOptions& right ) const
+ bool operator !=( const GSOptions& right ) const
{
return !this->operator ==( right );
}
@@ -475,15 +491,15 @@ struct Pcsx2Config
BITFIELD32()
bool
- CdvdVerboseReads:1, // enables cdvd read activity verbosely dumped to the console
- CdvdDumpBlocks:1, // enables cdvd block dumping
- EnablePatches:1, // enables patch detection and application
+ CdvdVerboseReads :1, // enables cdvd read activity verbosely dumped to the console
+ CdvdDumpBlocks :1, // enables cdvd block dumping
+ EnablePatches :1, // enables patch detection and application
// when enabled performs bios stub execution, skipping full sony bios + splash screens
- SkipBiosSplash:1,
+ SkipBiosSplash :1,
// enables simulated ejection of memory cards when loading savestates
- McdEnableEjection:1,
+ McdEnableEjection :1,
MultitapPort0_Enabled:1,
MultitapPort1_Enabled:1,
@@ -492,7 +508,7 @@ struct Pcsx2Config
BITFIELD_END
CpuOptions Cpu;
- VideoOptions Video;
+ GSOptions GS;
SpeedhackOptions Speedhacks;
GamefixOptions Gamefixes;
ProfilerOptions Profiler;
@@ -517,10 +533,12 @@ struct Pcsx2Config
return
OpEqu( bitset ) &&
OpEqu( Cpu ) &&
- OpEqu( Video ) &&
+ OpEqu( GS ) &&
OpEqu( Speedhacks ) &&
OpEqu( Gamefixes ) &&
OpEqu( Profiler ) &&
+ OpEqu( Log ) &&
+ OpEqu( Trace ) &&
OpEqu( BiosFilename );
}
@@ -530,23 +548,12 @@ struct Pcsx2Config
}
};
-//////////////////////////////////////////////////////////////////////////
-// Session Configuration Override Flags
-//
-// a handful of flags that can override user configurations for the current application session
-// only. This allows us to do things like force-disable recompilers if the memory allocations
-// for them fail.
-struct SessionOverrideFlags
-{
- bool
- ForceDisableEErec:1,
- ForceDisableIOPrec:1,
- ForceDisableVU0rec:1,
- ForceDisableVU1rec:1;
-};
-
extern const Pcsx2Config EmuConfig;
-extern SessionOverrideFlags g_Session;
+
+Pcsx2Config::GSOptions& SetGSConfig();
+ConsoleLogFilters& SetConsoleConfig();
+TraceLogFilters& SetTraceConfig();
+
/////////////////////////////////////////////////////////////////////////////////////////
// Helper Macros for Reading Emu Configurations.
@@ -557,10 +564,10 @@ extern SessionOverrideFlags g_Session;
#define CHECK_MACROVU0 // If defined uses mVU for VU Macro (COP2), else uses sVU
#define CHECK_MICROVU0 (EmuConfig.Cpu.Recompiler.UseMicroVU0)
#define CHECK_MICROVU1 (EmuConfig.Cpu.Recompiler.UseMicroVU1)
-#define CHECK_EEREC (!g_Session.ForceDisableEErec && EmuConfig.Cpu.Recompiler.EnableEE)
-#define CHECK_IOPREC (!g_Session.ForceDisableIOPrec && EmuConfig.Cpu.Recompiler.EnableIOP)
-#define CHECK_VU0REC (!g_Session.ForceDisableVU0rec && EmuConfig.Cpu.Recompiler.EnableVU0)
-#define CHECK_VU1REC (!g_Session.ForceDisableVU1rec && EmuConfig.Cpu.Recompiler.EnableVU1)
+#define CHECK_EEREC (EmuConfig.Cpu.Recompiler.EnableEE && GetSysCoreAlloc().RecSuccess_EE)
+#define CHECK_IOPREC (EmuConfig.Cpu.Recompiler.EnableIOP && GetSysCoreAlloc().RecSuccess_IOP)
+#define CHECK_VU0REC (EmuConfig.Cpu.Recompiler.EnableVU0 && GetSysCoreAlloc().RecSuccess_VU0)
+#define CHECK_VU1REC (EmuConfig.Cpu.Recompiler.EnableVU1 && GetSysCoreAlloc().RecSuccess_VU1)
//------------ SPECIAL GAME FIXES!!! ---------------
#define NUM_OF_GAME_FIXES 7
diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp
index fe44142b59..8551c31549 100644
--- a/pcsx2/Counters.cpp
+++ b/pcsx2/Counters.cpp
@@ -160,7 +160,7 @@ static u64 m_iStart=0;
struct vSyncTimingInfo
{
- u32 Framerate; // frames per second * 100 (so 2500 for PAL and 2997 for NTSC)
+ Fixed100 Framerate; // frames per second (8 bit fixed)
u32 Render; // time from vblank end to vblank start (cycles)
u32 Blank; // time from vblank start to vblank end (cycles)
@@ -174,34 +174,31 @@ struct vSyncTimingInfo
static vSyncTimingInfo vSyncInfo;
-static void vSyncInfoCalc( vSyncTimingInfo* info, u32 framesPerSecond, u32 scansPerFrame )
+static void vSyncInfoCalc( vSyncTimingInfo* info, Fixed100 framesPerSecond, u32 scansPerFrame )
{
- // Important: Cannot use floats or doubles here. The emulator changes rounding modes
- // depending on user-set speedhack options, and it can break float/double code
- // (as in returning infinities and junk)
+ // I use fixed point math here to have strict control over rounding errors. --air
// NOTE: mgs3 likes a /4 vsync, but many games prefer /2. This seems to indicate a
// problem in the counters vsync gates somewhere.
- u64 Frame = ((u64)PS2CLK * 1000000ULL) / framesPerSecond;
- u64 HalfFrame = Frame / 2;
- u64 Blank = HalfFrame / 2; // two blanks and renders per frame
- u64 Render = HalfFrame - Blank; // so use the half-frame value for these...
+ u64 Frame = ((u64)PS2CLK * 1000000ULL) / (framesPerSecond*100).ToIntRounded();
+ u64 HalfFrame = Frame / 2;
+ u64 Blank = HalfFrame / 2; // two blanks and renders per frame
+ u64 Render = HalfFrame - Blank; // so use the half-frame value for these...
// Important! The hRender/hBlank timers should be 50/50 for best results.
- // In theory a 70%/30% ratio would be more correct but in practice it runs
- // like crap and totally screws audio synchronization and other things.
+ // (this appears to be what the real EE's timing crystal does anyway)
- u64 Scanline = Frame / scansPerFrame;
- u64 hBlank = Scanline / 2;
- u64 hRender = Scanline - hBlank;
+ u64 Scanline = Frame / scansPerFrame;
+ u64 hBlank = Scanline / 2;
+ u64 hRender = Scanline - hBlank;
- info->Framerate = framesPerSecond;
- info->Render = (u32)(Render/10000);
- info->Blank = (u32)(Blank/10000);
+ info->Framerate = framesPerSecond;
+ info->Render = (u32)(Render/10000);
+ info->Blank = (u32)(Blank/10000);
- info->hRender = (u32)(hRender/10000);
- info->hBlank = (u32)(hBlank/10000);
+ info->hRender = (u32)(hRender/10000);
+ info->hBlank = (u32)(hBlank/10000);
info->hScanlinesPerFrame = scansPerFrame;
// Apply rounding:
@@ -226,53 +223,64 @@ static void vSyncInfoCalc( vSyncTimingInfo* info, u32 framesPerSecond, u32 scans
u32 UpdateVSyncRate()
{
- static const char *limiterMsg = "Framelimiter rate updated (UpdateVSyncRate): %d.%d fps";
+ XMMRegisters::Freeze();
+ MMXRegisters::Freeze();
- // fixme - According to some docs, progressive-scan modes actually refresh slower than
- // interlaced modes. But I can't fathom how, since the refresh rate is a function of
- // the television and all the docs I found on TVs made no indication that they ever
- // run anything except their native refresh rate.
-
- //#define VBLANK_NTSC ((Config.PsxType & 2) ? 59.94 : 59.82) //59.94 is more precise
- //#define VBLANK_PAL ((Config.PsxType & 2) ? 50.00 : 49.76)
+ // Notice: (and I probably repeat this elsewhere, but it's worth repeating)
+ // The PS2's vsync timer is an *independent* crystal that is fixed to either 59.94 (NTSC)
+ // or 50.0 (PAL) Hz. It has *nothing* to do with real TV timings or the real vsync of
+ // the GS's output circuit. It is the same regardless if the GS is outputting interlace
+ // or progressive scan content. Indications are that it is also a simple 50/50 timer and
+ // that it does not actually measure Vblank/Vdraw zones accurately (which would be like
+ // 1/5 and 4/5 ratios).
+
+ Fixed100 framerate;
+ u32 scanlines;
+ bool isCustom;
if( gsRegionMode == Region_PAL )
{
- if( vSyncInfo.Framerate != FRAMERATE_PAL )
- vSyncInfoCalc( &vSyncInfo, FRAMERATE_PAL, SCANLINES_TOTAL_PAL );
+ isCustom = (EmuConfig.GS.FrameratePAL != 50.0);
+ framerate = EmuConfig.GS.FrameratePAL / 2;
+ scanlines = SCANLINES_TOTAL_PAL;
}
else
{
- if( vSyncInfo.Framerate != FRAMERATE_NTSC )
- vSyncInfoCalc( &vSyncInfo, FRAMERATE_NTSC, SCANLINES_TOTAL_NTSC );
+ isCustom = (EmuConfig.GS.FramerateNTSC != 59.94);
+ framerate = EmuConfig.GS.FramerateNTSC / 2;
+ scanlines = SCANLINES_TOTAL_NTSC;
+ }
+
+ if( vSyncInfo.Framerate != framerate )
+ {
+ vSyncInfoCalc( &vSyncInfo, framerate, scanlines );
+ Console.WriteLn( Color_Blue, "(UpdateVSyncRate) Mode Changed to %s.", ( gsRegionMode == Region_PAL ) ? "PAL" : "NTSC" );
+ if( isCustom )
+ Console.Indent().WriteLn( Color_StrongBlue, "... with user configured refresh rate: %.02f Hz", framerate.ToFloat() );
+
+ hsyncCounter.CycleT = vSyncInfo.hRender; // Amount of cycles before the counter will be updated
+ vsyncCounter.CycleT = vSyncInfo.Render; // Amount of cycles before the counter will be updated
+
+ cpuRcntSet();
}
- hsyncCounter.CycleT = vSyncInfo.hRender; // Amount of cycles before the counter will be updated
- vsyncCounter.CycleT = vSyncInfo.Render; // Amount of cycles before the counter will be updated
+ Fixed100 fpslimit = framerate *
+ ( pxAssert( EmuConfig.GS.LimitScalar > 0 ) ? EmuConfig.GS.LimitScalar : 1.0 );
- if( EmuConfig.Video.EnableFrameLimiting && (EmuConfig.Video.FpsLimit > 0) )
+ //s64 debugme = GetTickFrequency() / 3000;
+ s64 ticks = (GetTickFrequency()*500) / (fpslimit * 1000).ToIntRounded();
+
+ if( m_iTicks != ticks )
{
- s64 ticks = GetTickFrequency() / EmuConfig.Video.FpsLimit;
- if( m_iTicks != ticks )
- {
- m_iTicks = ticks;
- gsOnModeChanged( vSyncInfo.Framerate, m_iTicks );
- Console.WriteLn( limiterMsg, EmuConfig.Video.FpsLimit, 0 );
- }
- }
- else
- {
- s64 ticks = (GetTickFrequency() * 50) / vSyncInfo.Framerate;
- if( m_iTicks != ticks )
- {
- m_iTicks = ticks;
- gsOnModeChanged( vSyncInfo.Framerate, m_iTicks );
- Console.WriteLn( limiterMsg, vSyncInfo.Framerate/50, (vSyncInfo.Framerate*2)%100 );
- }
+ m_iTicks = ticks;
+ gsOnModeChanged( vSyncInfo.Framerate, m_iTicks );
+ Console.WriteLn( "(UpdateVSyncRate) FPS Limit Changed : %.02f fps", fpslimit.ToFloat()*2 );
}
m_iStart = GetCPUTicks();
- cpuRcntSet();
+
+ XMMRegisters::Thaw();
+ MMXRegisters::Thaw();
return (u32)m_iTicks;
}
@@ -289,16 +297,11 @@ extern int limitOn;
static __forceinline void frameLimit()
{
// 999 means the user would rather just have framelimiting turned off...
- if( /*!EmuConfig.Video.EnableFrameLimiting*/ !limitOn || EmuConfig.Video.FpsLimit >= 999 ) return;
+ if( !EmuConfig.GS.FrameLimitEnable ) return;
- s64 sDeltaTime;
- u64 uExpectedEnd;
- u64 iEnd;
-
- uExpectedEnd = m_iStart + m_iTicks;
- iEnd = GetCPUTicks();
-
- sDeltaTime = iEnd - uExpectedEnd;
+ u64 uExpectedEnd = m_iStart + m_iTicks;
+ u64 iEnd = GetCPUTicks();
+ s64 sDeltaTime = iEnd - uExpectedEnd;
// If the framerate drops too low, reset the expected value. This avoids
// excessive amounts of "fast forward" syndrome which would occur if we
@@ -307,12 +310,6 @@ static __forceinline void frameLimit()
if( sDeltaTime > m_iTicks*8 )
{
m_iStart = iEnd - m_iTicks;
-
- // Let the GS Skipper know we lost time.
- // Keeps the GS skipper from trying to catch up to a framerate
- // that the limiter already gave up on.
-
- gsSyncLimiterLostTime( (s32)(m_iStart - uExpectedEnd) );
return;
}
@@ -386,7 +383,7 @@ static __forceinline void VSyncEnd(u32 sCycle)
iFrame++;
- gsPostVsyncEnd( true );
+ gsPostVsyncEnd();
hwIntcIrq(INTC_VBLANK_E); // HW Irq
psxVBlankEnd(); // psxCounters vBlank End
diff --git a/pcsx2/Counters.h b/pcsx2/Counters.h
index 921125434f..5cc1496477 100644
--- a/pcsx2/Counters.h
+++ b/pcsx2/Counters.h
@@ -92,7 +92,7 @@ struct SyncCounter
//------------------------------------------------------------------
// NTSC Timing Information!!! (some scanline info is guessed)
//------------------------------------------------------------------
-#define FRAMERATE_NTSC 2997// frames per second * 100 (29.97)
+#define FRAMERATE_NTSC 29.97 // frames per second
#define SCANLINES_TOTAL_NTSC 525 // total number of scanlines
#define SCANLINES_VSYNC_NTSC 3 // scanlines that are used for syncing every half-frame
@@ -103,7 +103,7 @@ struct SyncCounter
//------------------------------------------------------------------
// PAL Timing Information!!! (some scanline info is guessed)
//------------------------------------------------------------------
-#define FRAMERATE_PAL 2500// frames per second * 100 (25)
+#define FRAMERATE_PAL 25.0// frames per second * 100 (25)
#define SCANLINES_TOTAL_PAL 625 // total number of scanlines per frame
#define SCANLINES_VSYNC_PAL 5 // scanlines that are used for syncing every half-frame
@@ -145,7 +145,7 @@ extern void rcntWhold(int index, u32 value);
extern u32 rcntRcount(int index);
extern u32 rcntCycle(int index);
-u32 UpdateVSyncRate();
-void frameLimitReset();
+extern u32 UpdateVSyncRate();
+extern void frameLimitReset();
#endif /* __COUNTERS_H__ */
diff --git a/pcsx2/DebugTools/DisVU1Micro.cpp b/pcsx2/DebugTools/DisVU1Micro.cpp
index e4c582f14d..d4d2fb1fc4 100644
--- a/pcsx2/DebugTools/DisVU1Micro.cpp
+++ b/pcsx2/DebugTools/DisVU1Micro.cpp
@@ -31,7 +31,7 @@ typedef char* (*TdisR5900F)DisFInterface;
// These macros are used to assemble the disassembler functions
#define MakeDisF(fn, b) \
char* fn DisFInterface { \
- if( !CHECK_VU1REC ) sprintf (ostr, "%8.8x %8.8x:", pc, code); \
+ if( !!CpuVU1.IsInterpreter ) sprintf (ostr, "%8.8x %8.8x:", pc, code); \
else ostr[0] = 0; \
b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \
}
@@ -52,47 +52,47 @@ typedef char* (*TdisR5900F)DisFInterface;
}
#define dCP2128f(i) { \
- if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \
+ if( !CpuVU1.IsInterpreter ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \
else sprintf(ostr, "%s w=%f (%8.8x) z=%f (%8.8x) y=%f (%8.8xl) x=%f (%8.8x) (%s),", ostr, VU1.VF[i].f.w, VU1.VF[i].UL[3], VU1.VF[i].f.z, VU1.VF[i].UL[2], VU1.VF[i].f.y, VU1.VF[i].UL[1], VU1.VF[i].f.x, VU1.VF[i].UL[0], disRNameCP2f[i]); \
} \
#define dCP232x(i) { \
- if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \
+ if( !CpuVU1.IsInterpreter ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \
else sprintf(ostr, "%s x=%f (%s),", ostr, VU1.VF[i].f.x, disRNameCP2f[i]); \
} \
#define dCP232y(i) { \
- if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \
+ if( !CpuVU1.IsInterpreter ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \
else sprintf(ostr, "%s y=%f (%s),", ostr, VU1.VF[i].f.y, disRNameCP2f[i]); \
} \
#define dCP232z(i) { \
- if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \
+ if( !CpuVU1.IsInterpreter ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \
else sprintf(ostr, "%s z=%f (%s),", ostr, VU1.VF[i].f.z, disRNameCP2f[i]); \
}
#define dCP232w(i) { \
- if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \
+ if( !CpuVU1.IsInterpreter ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \
else sprintf(ostr, "%s w=%f (%s),", ostr, VU1.VF[i].f.w, disRNameCP2f[i]); \
}
#define dCP2ACCf() { \
- if( CHECK_VU1REC ) sprintf(ostr, "%s ACC,", ostr); \
+ if( !CpuVU1.IsInterpreter ) sprintf(ostr, "%s ACC,", ostr); \
else sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU1.ACC.f.w, VU1.ACC.f.z, VU1.ACC.f.y, VU1.ACC.f.x); \
} \
#define dCP232i(i) { \
- if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \
+ if( !CpuVU1.IsInterpreter ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \
else sprintf(ostr, "%s %8.8x (%s),", ostr, VU1.VI[i].UL, disRNameCP2i[i]); \
}
#define dCP232iF(i) { \
- if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \
+ if( !CpuVU1.IsInterpreter ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \
else sprintf(ostr, "%s %f (%s),", ostr, VU1.VI[i].F, disRNameCP2i[i]); \
}
#define dCP232f(i, j) { \
- if( CHECK_VU1REC ) sprintf(ostr, "%s %s%s,", ostr, disRNameCP2f[i], CP2VFnames[j]); \
+ if( !CpuVU1.IsInterpreter ) sprintf(ostr, "%s %s%s,", ostr, disRNameCP2f[i], CP2VFnames[j]); \
else sprintf(ostr, "%s %s=%f (%s),", ostr, CP2VFnames[j], VU1.VF[i].F[j], disRNameCP2f[i]); \
}
diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp
index d5a1cc6629..83391f23ec 100644
--- a/pcsx2/GS.cpp
+++ b/pcsx2/GS.cpp
@@ -30,42 +30,9 @@ u32 CSRw;
__aligned16 u8 g_RealGSMem[0x2000];
extern int m_nCounters[];
-// FrameSkipping Stuff
-// Yuck, iSlowStart is needed by the MTGS, so can't make it static yet.
-
-u64 m_iSlowStart=0;
-static s64 m_iSlowTicks=0;
-static bool m_justSkipped = false;
-static bool m_StrictSkipping = false;
-
-void _gs_ChangeTimings( u32 framerate, u32 iTicks )
+void gsOnModeChanged( Fixed100 framerate, u32 newTickrate )
{
- m_iSlowStart = GetCPUTicks();
-
- u32 frameSkipThreshold = EmuConfig.Video.FpsSkip*50;
- if( frameSkipThreshold == 0)
- {
- // default: load the frameSkipThreshold with a value roughly 90% of the PS2 native framerate
- frameSkipThreshold = ( framerate * 242 ) / 256;
- }
-
- m_iSlowTicks = ( GetTickFrequency() * 50 ) / frameSkipThreshold;
-
- // sanity check against users who set a "minimum" frame that's higher
- // than the maximum framerate. Also, if framerates are within 1/3300th
- // of a second of each other, assume strict skipping (it's too close,
- // and could cause excessive skipping).
-
- if( m_iSlowTicks <= (iTicks + ((s64)GetTickFrequency()/3300)) )
- {
- m_iSlowTicks = iTicks;
- m_StrictSkipping = true;
- }
-}
-
-void gsOnModeChanged( u32 framerate, u32 newTickrate )
-{
- GetMTGS().SendSimplePacket( GS_RINGTYPE_MODECHANGE, framerate, newTickrate, 0 );
+ GetMTGS().SendSimplePacket( GS_RINGTYPE_MODECHANGE, framerate.Raw, newTickrate, 0 );
}
static bool gsIsInterlaced = false;
@@ -77,7 +44,6 @@ void gsSetRegionMode( GS_RegionMode region )
if( gsRegionMode == region ) return;
gsRegionMode = region;
- Console.WriteLn( "%s Display Mode Initialized.", (( gsRegionMode == Region_PAL ) ? "PAL" : "NTSC") );
UpdateVSyncRate();
}
@@ -92,10 +58,7 @@ void gsReset()
{
GetMTGS().ResetGS();
- gsOnModeChanged(
- (gsRegionMode == Region_NTSC) ? FRAMERATE_NTSC : FRAMERATE_PAL,
- UpdateVSyncRate()
- );
+ UpdateVSyncRate();
memzero(g_RealGSMem);
@@ -353,161 +316,60 @@ void gsIrq() {
hwIntcIrq(INTC_GS);
}
-void gsSyncLimiterLostTime( s32 deltaTime )
+// --------------------------------------------------------------------------------------
+// gsFrameSkip
+// --------------------------------------------------------------------------------------
+// This function regulates the frameskipping status of the GS. Our new frameskipper for
+// 0.9.7 is a very simple logic pattern compared to the old mess. The goal now is to provide
+// the most compatible and efficient frameskip, instead of doing the adaptive logic of
+// 0.9.6. This is almost a necessity because of how many games treat the GS: they upload
+// great amounts of data while rendering 2 frames at a time (using double buffering), and
+// then use a simple pageswap to display the contents of the second frame for that vsync.
+// (this approach is mostly seen on interlace games; progressive games less so)
+// The result is that any skip pattern besides a fully consistent 2on,2off would reuslt in
+// tons of missing geometry, rendering frameskip useless.
+//
+// So instead we use a simple "always skipping" or "never skipping" logic.
+//
+// EE vs MTGS:
+// This function does not regulate frame limiting, meaning it does no stalling. Stalling
+// functions are performed by the EE, which itself uses thread sleep logic to avoid spin
+// waiting as much as possible (maximizes CPU resource availability for the GS).
+
+__forceinline void gsFrameSkip()
{
- // This sync issue applies only to configs that are trying to maintain
- // a perfect "specific" framerate (where both min and max fps are the same)
- // any other config will eventually equalize out.
+ if( !EmuConfig.GS.FrameSkipEnable ) return;
- if( !m_StrictSkipping ) return;
+ static int consec_skipped = 0;
+ static int consec_drawn = 0;
+ static bool isSkipping = false;
+
+ GSsetFrameSkip( isSkipping );
- //Console.WriteLn("LostTime on the EE!");
-
- GetMTGS().SendSimplePacket(
- GS_RINGTYPE_STARTTIME,
- deltaTime,
- 0,
- 0
- );
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// FrameSkipper - Measures delta time between calls and issues frameskips
-// it the time is too long. Also regulates the status of the EE's framelimiter.
-
-// This function does not regulate frame limiting, meaning it does no stalling.
-// Stalling functions are performed by the EE: If the MTGS were throtted and not
-// the EE, the EE would fill the ringbuffer while the MTGS regulated frames --
-// fine for most situations but could result in literally dozens of frames queued
-// up in the ringbuffer durimg some game menu screens; which in turn would result
-// in a half-second lag of keystroke actions becoming visible to the user (bad!).
-
-// Alternative: Instead of this, I could have everything regulated here, and then
-// put a framecount limit on the MTGS ringbuffer. But that seems no less complicated
-// and would also mean that aforementioned menus would still be laggy by whatever
-// frame count threshold. This method is more responsive.
-
-__forceinline void gsFrameSkip( bool forceskip )
-{
- static u8 FramesToRender = 0;
- static u8 FramesToSkip = 0;
-
- if( !EmuConfig.Video.EnableFrameSkipping ) return;
-
- // FrameSkip and VU-Skip Magic!
- // Skips a sequence of consecutive frames after a sequence of rendered frames
-
- // This is the least number of consecutive frames we will render w/o skipping
- const int noSkipFrames = ((EmuConfig.Video.ConsecutiveFrames>0) ? EmuConfig.Video.ConsecutiveFrames : 1);
- // This is the number of consecutive frames we will skip
- const int yesSkipFrames = ((EmuConfig.Video.ConsecutiveSkip>0) ? EmuConfig.Video.ConsecutiveSkip : 1);
-
- const u64 iEnd = GetCPUTicks();
- const s64 uSlowExpectedEnd = m_iSlowStart + m_iSlowTicks;
- const s64 sSlowDeltaTime = iEnd - uSlowExpectedEnd;
-
- m_iSlowStart = uSlowExpectedEnd;
-
- if( forceskip )
+ if( isSkipping )
{
- if( !FramesToSkip )
+ ++consec_skipped;
+ if( consec_skipped >= EmuConfig.GS.ConsecutiveSkip )
{
- //Console.Status( "- Skipping some VUs!" );
-
- GSsetFrameSkip( 1 );
- FramesToRender = noSkipFrames;
- FramesToSkip = 1; // just set to 1
-
- // We're already skipping, so FramesToSkip==1 will just restore the gsFrameSkip
- // setting and reset our delta times as needed.
+ consec_skipped = 0;
+ isSkipping = false;
}
- return;
}
-
- if( FramesToRender == 0 )
+ else
{
- // -- Standard operation section --
- // Means neither skipping frames nor force-rendering consecutive frames.
-
- if( sSlowDeltaTime > 0 )
+ ++consec_drawn;
+ if( consec_drawn >= EmuConfig.GS.ConsecutiveFrames )
{
- // The game is running below the minimum framerate.
- // But don't start skipping yet! That would be too sensitive.
- // So the skipping code is only engaged if the SlowDeltaTime falls behind by
- // a full frame, or if we're already skipping (in which case we don't care
- // to avoid errant skips).
-
- // Note: The MTGS can go out of phase from the EE, which means that the
- // variance for a "nominal" framerate can range from 0 to m_iSlowTicks.
- // We also check for that here.
-
- if( (m_justSkipped && (sSlowDeltaTime > m_iSlowTicks)) ||
- (sSlowDeltaTime > m_iSlowTicks*2) )
- {
- GSsetFrameSkip(1);
- FramesToRender = noSkipFrames+1;
- FramesToSkip = yesSkipFrames;
- }
+ consec_drawn = 0;
+ isSkipping = true;
}
- else
- {
- // Running at or above full speed, so reset the StartTime since the Limiter
- // will muck things up. (special case: if skip and limit fps are equal then
- // we don't reset starttime since it would cause desyncing. We let the EE
- // regulate it via calls to gsSyncLimiterStartTime).
-
- if( !m_StrictSkipping )
- m_iSlowStart = iEnd;
- }
- m_justSkipped = false;
- return;
- }
- else if( FramesToSkip > 0 )
- {
- // -- Frames-a-Skippin' Section --
-
- FramesToSkip--;
-
- if( FramesToSkip == 0 )
- {
- // Skipped our last frame, so restore non-skip behavior
-
- GSsetFrameSkip(0);
-
- // Note: If we lag behind by 250ms then it's time to give up on the idea
- // of catching up. Force the game to slow down by resetting iStart to
- // something closer to iEnd.
-
- if( sSlowDeltaTime > (m_iSlowTicks + ((s64)GetTickFrequency() / 4)) )
- {
- //Console.Status( "Frameskip couldn't skip enough -- had to lose some time!" );
- m_iSlowStart = iEnd - m_iSlowTicks;
- }
-
- m_justSkipped = true;
- }
- else
- return;
- }
-
- //Console.WriteLn( "Consecutive Frames -- Lateness: %d", (int)( sSlowDeltaTime / m_iSlowTicks ) );
-
- // -- Consecutive frames section --
- // Force-render consecutive frames without skipping.
-
- FramesToRender--;
-
- if( sSlowDeltaTime < 0 )
- {
- m_iSlowStart = iEnd;
}
}
-// updategs - if FALSE the gs will skip the frame.
-void gsPostVsyncEnd( bool updategs )
+void gsPostVsyncEnd()
{
*(u32*)(PS2MEM_GS+0x1000) ^= 0x2000; // swap the vsync field
- GetMTGS().PostVsyncEnd( updategs );
+ GetMTGS().PostVsyncEnd();
}
void _gs_ResetFrameskip()
@@ -521,15 +383,6 @@ void gsResetFrameSkip()
GetMTGS().SendSimplePacket(GS_RINGTYPE_FRAMESKIP, 0, 0, 0);
}
-void gsDynamicSkipEnable()
-{
- if( !m_StrictSkipping ) return;
-
- GetMTGS().WaitGS();
- m_iSlowStart = GetCPUTicks();
- frameLimitReset();
-}
-
void SaveStateBase::gsFreeze()
{
FreezeMem(PS2MEM_GS, 0x2000);
diff --git a/pcsx2/GS.h b/pcsx2/GS.h
index 276fe5835f..85a86bae65 100644
--- a/pcsx2/GS.h
+++ b/pcsx2/GS.h
@@ -74,7 +74,6 @@ enum MTGS_RingCommand
, GS_RINGTYPE_WRITECSR
, GS_RINGTYPE_MODECHANGE // for issued mode changes.
, GS_RINGTYPE_CRC
-, GS_RINGTYPE_STARTTIME // special case for min==max fps frameskip settings
};
@@ -151,7 +150,7 @@ public:
u8* GetDataPacketPtr() const;
void SetEvent();
- void PostVsyncEnd( bool updategs );
+ void PostVsyncEnd();
protected:
void OpenPlugin();
@@ -171,10 +170,10 @@ protected:
void ExecuteTaskInThread();
};
-// GetMtgsThread() is a required external implementation. This function is *NOT*
-// provided by the PCSX2 core library. It provides an interface for the linking User
-// Interface apps or DLLs to reference their own instance of SysMtgsThread (also allowing
-// them to extend the class and override virtual methods).
+// GetMTGS() is a required external implementation. This function is *NOT* provided
+// by the PCSX2 core library. It provides an interface for the linking User Interface
+// apps or DLLs to reference their own instance of SysMtgsThread (also allowing them
+// to extend the class and override virtual methods).
//
SysMtgsThread& GetMTGS();
@@ -185,17 +184,14 @@ extern void gsInit();
extern s32 gsOpen();
extern void gsClose();
extern void gsReset();
-extern void gsOnModeChanged( u32 framerate, u32 newTickrate );
+extern void gsOnModeChanged( Fixed100 framerate, u32 newTickrate );
extern void gsSetRegionMode( GS_RegionMode isPal );
extern void gsResetFrameSkip();
-extern void gsSyncLimiterLostTime( s32 deltaTime );
-extern void gsDynamicSkipEnable();
-extern void gsPostVsyncEnd( bool updategs );
-extern void gsFrameSkip( bool forceskip );
+extern void gsPostVsyncEnd();
+extern void gsFrameSkip();
// Some functions shared by both the GS and MTGS
extern void _gs_ResetFrameskip();
-extern void _gs_ChangeTimings( u32 framerate, u32 iTicks );
// used for resetting GIF fifo
@@ -222,7 +218,6 @@ extern u64 gsRead64(u32 mem);
void gsIrq();
extern u32 CSRw;
-extern u64 m_iSlowStart;
// GS Playback
enum gsrun
diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp
index 73dbc4323e..a3d7e68d56 100644
--- a/pcsx2/MTGS.cpp
+++ b/pcsx2/MTGS.cpp
@@ -148,9 +148,9 @@ void SysMtgsThread::ResetGS()
GIFPath_Reset();
}
-void SysMtgsThread::PostVsyncEnd( bool updategs )
+void SysMtgsThread::PostVsyncEnd()
{
- SendSimplePacket( GS_RINGTYPE_VSYNC, (*(u32*)(PS2MEM_GS+0x1000)&0x2000), updategs, 0 );
+ SendSimplePacket( GS_RINGTYPE_VSYNC, (*(u32*)(PS2MEM_GS+0x1000)&0x2000), 0, 0 );
// Alter-frame flushing! Restarts the ringbuffer (wraps) on every other frame. This is a
// mandatory feature that prevents the MTGS from queuing more than 2 frames at any time.
@@ -198,6 +198,8 @@ void SysMtgsThread::OpenPlugin()
else
result = GSopen( (void*)&pDsp, "PCSX2", renderswitch ? 2 : 1 );
+ GSsetVsync( EmuConfig.GS.FrameLimitEnable && EmuConfig.GS.VsyncEnable );
+
if( result != 0 )
{
DevCon.WriteLn( "GSopen Failed: return code: 0x%x", result );
@@ -352,7 +354,7 @@ void SysMtgsThread::ExecuteTaskInThread()
{
MTGS_LOG( "(MTGS Packet Read) ringtype=Vsync, field=%u, skip=%s", tag.data[0], tag.data[1] ? "true" : "false" );
GSvsync(tag.data[0]);
- gsFrameSkip( !tag.data[1] );
+ gsFrameSkip();
if( PADupdate != NULL )
PADupdate(0);
@@ -416,17 +418,13 @@ void SysMtgsThread::ExecuteTaskInThread()
break;
case GS_RINGTYPE_MODECHANGE:
- _gs_ChangeTimings( tag.data[0], tag.data[1] );
+ // [TODO] some frameskip sync logic might be needed here!
break;
case GS_RINGTYPE_CRC:
GSsetGameCRC( tag.data[0], 0 );
break;
- case GS_RINGTYPE_STARTTIME:
- m_iSlowStart += tag.data[0];
- break;
-
#ifdef PCSX2_DEVBUILD
default:
Console.Error("GSThreadProc, bad packet (%x) at m_RingPos: %x, m_WritePos: %x", tag.command, m_RingPos, m_WritePos);
@@ -568,7 +566,7 @@ void SysMtgsThread::SendDataPacket()
m_WritePos = temp;
- if( EmuConfig.Video.SynchronousMTGS )
+ if( EmuConfig.GS.SynchronousMTGS )
{
WaitGS();
}
@@ -854,7 +852,7 @@ void SysMtgsThread::RestartRingbuffer( uint packsize )
m_WritePos = 0;
m_QueuedFrameCount = 0;
- if( EmuConfig.Video.SynchronousMTGS )
+ if( EmuConfig.GS.SynchronousMTGS )
WaitGS();
}
@@ -918,7 +916,7 @@ __forceinline void SysMtgsThread::_FinishSimplePacket( uint future_writepos )
pxAssert( future_writepos != volatize(m_RingPos) );
m_WritePos = future_writepos;
- if( EmuConfig.Video.SynchronousMTGS )
+ if( EmuConfig.GS.SynchronousMTGS )
WaitGS();
else
++m_CopyDataTally;
diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp
index 298c9d3e2b..825196059d 100644
--- a/pcsx2/Pcsx2Config.cpp
+++ b/pcsx2/Pcsx2Config.cpp
@@ -204,35 +204,38 @@ void Pcsx2Config::CpuOptions::LoadSave( IniInterface& ini )
Recompiler.LoadSave( ini );
}
-Pcsx2Config::VideoOptions::VideoOptions()
+Pcsx2Config::GSOptions::GSOptions()
{
- EnableFrameLimiting = false;
- EnableFrameSkipping = false;
+ FrameLimitEnable = true;
+ FrameSkipEnable = false;
SynchronousMTGS = false;
DefaultRegionMode = Region_NTSC;
- FpsTurbo = 60*4;
- FpsLimit = 60;
- FpsSkip = 55;
ConsecutiveFrames = 2;
- ConsecutiveSkip = 1;
+ ConsecutiveSkip = 2;
+
+ LimitScalar = 1.0;
+ FramerateNTSC = 59.94;
+ FrameratePAL = 50.0;
}
-void Pcsx2Config::VideoOptions::LoadSave( IniInterface& ini )
+void Pcsx2Config::GSOptions::LoadSave( IniInterface& ini )
{
- VideoOptions defaults;
- IniScopedGroup path( ini, L"Video" );
+ GSOptions defaults;
+ IniScopedGroup path( ini, L"GS" );
- IniEntry( EnableFrameLimiting );
- IniEntry( EnableFrameSkipping );
+ IniEntry( FrameLimitEnable );
+ IniEntry( FrameSkipEnable );
+ IniEntry( VsyncEnable );
+
+ IniEntry( LimitScalar );
+ IniEntry( FramerateNTSC );
+ IniEntry( FrameratePAL );
static const wxChar * const ntsc_pal_str[2] = { L"ntsc", L"pal" };
ini.EnumEntry( L"DefaultRegionMode", DefaultRegionMode, ntsc_pal_str, defaults.DefaultRegionMode );
- IniEntry( FpsTurbo );
- IniEntry( FpsLimit );
- IniEntry( FpsSkip );
IniEntry( ConsecutiveFrames );
IniEntry( ConsecutiveSkip );
}
@@ -251,9 +254,9 @@ void Pcsx2Config::GamefixOptions::LoadSave( IniInterface& ini )
IniBitBool( XgKickHack );
}
-Pcsx2Config::Pcsx2Config() :
- bitset( 0 )
+Pcsx2Config::Pcsx2Config()
{
+ bitset = 0;
}
void Pcsx2Config::LoadSave( IniInterface& ini )
@@ -274,13 +277,14 @@ void Pcsx2Config::LoadSave( IniInterface& ini )
// Process various sub-components:
- Speedhacks.LoadSave( ini );
- Cpu.LoadSave( ini );
- Video.LoadSave( ini );
- Gamefixes.LoadSave( ini );
- Profiler.LoadSave( ini );
+ Speedhacks .LoadSave( ini );
+ Cpu .LoadSave( ini );
+ GS .LoadSave( ini );
+ Gamefixes .LoadSave( ini );
+ Profiler .LoadSave( ini );
- Trace.LoadSave( ini );
+ Trace .LoadSave( ini );
+ Log .LoadSave( ini );
ini.Flush();
}
diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp
index f6ba564aed..bad0f47b59 100644
--- a/pcsx2/PluginManager.cpp
+++ b/pcsx2/PluginManager.cpp
@@ -146,6 +146,7 @@ _GSprintf GSprintf;
_GSsetBaseMem GSsetBaseMem;
_GSsetGameCRC GSsetGameCRC;
_GSsetFrameSkip GSsetFrameSkip;
+_GSsetVsync GSsetVsync;
_GSsetupRecording GSsetupRecording;
_GSreset GSreset;
_GSwriteCSR GSwriteCSR;
@@ -154,6 +155,8 @@ static void CALLBACK GS_makeSnapshot(const char *path) {}
static void CALLBACK GS_setGameCRC(u32 crc, int gameopts) {}
static void CALLBACK GS_irqCallback(void (*callback)()) {}
static void CALLBACK GS_setFrameSkip(int frameskip) {}
+static void CALLBACK GS_setVsync(int enabled) {}
+static void CALLBACK GS_setFullscreen(int enabled) {}
static void CALLBACK GS_changeSaveState( int, const char* filename ) {}
static void CALLBACK GS_printf(int timeout, char *fmt, ...)
{
@@ -283,6 +286,7 @@ static const LegacyApi_ReqMethod s_MethMessReq_GS[] =
{ "GSsetGameCRC", (vMeth**)&GSsetGameCRC, (vMeth*)GS_setGameCRC },
{ "GSsetFrameSkip", (vMeth**)&GSsetFrameSkip, (vMeth*)GS_setFrameSkip },
+ { "GSsetVsync", (vMeth**)&GSsetVsync, (vMeth*)GS_setVsync },
{ "GSchangeSaveState",(vMeth**)&GSchangeSaveState,(vMeth*)GS_changeSaveState },
{ NULL }
};
diff --git a/pcsx2/PrecompiledHeader.h b/pcsx2/PrecompiledHeader.h
index 2e9f6a9ccf..bdbade65fa 100644
--- a/pcsx2/PrecompiledHeader.h
+++ b/pcsx2/PrecompiledHeader.h
@@ -80,6 +80,7 @@ typedef int BOOL;
#include "i18n.h"
#include "Utilities/Assertions.h"
+#include "Utilities/FixedPointTypes.h"
#include "Utilities/wxBaseTools.h"
#include "Utilities/ScopedPtr.h"
#include "Utilities/Path.h"
diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp
index 78b3afdeac..1f0e89ffb8 100644
--- a/pcsx2/R5900.cpp
+++ b/pcsx2/R5900.cpp
@@ -550,7 +550,7 @@ __forceinline void cpuTestHwInts() {
void cpuExecuteBios()
{
// Set the video mode to user's default request:
- gsSetRegionMode( (GS_RegionMode)EmuConfig.Video.DefaultRegionMode );
+ gsSetRegionMode( (GS_RegionMode)EmuConfig.GS.DefaultRegionMode );
Console.WriteLn( "Executing Bios Stub..." );
diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp
index e5a182a4e0..588975773b 100644
--- a/pcsx2/System.cpp
+++ b/pcsx2/System.cpp
@@ -32,8 +32,29 @@ SrcType_PageFault Source_PageFault;
const Pcsx2Config EmuConfig;
-// disable all session overrides by default...
-SessionOverrideFlags g_Session = {false};
+// Provides an accessor for quick modification of GS options. All GS options are allowed to be
+// changed "on the fly" by the *main/gui thread only*.
+Pcsx2Config::GSOptions& SetGSConfig()
+{
+ //DbgCon.WriteLn( "Direct modification of EmuConfig.GS detected" );
+ AllowFromMainThreadOnly();
+ return const_cast(EmuConfig.GS);
+}
+
+ConsoleLogFilters& SetConsoleConfig()
+{
+ //DbgCon.WriteLn( "Direct modification of EmuConfig.Log detected" );
+ AllowFromMainThreadOnly();
+ return const_cast(EmuConfig.Log);
+}
+
+TraceLogFilters& SetTraceConfig()
+{
+ //DbgCon.WriteLn( "Direct modification of EmuConfig.TraceLog detected" );
+ AllowFromMainThreadOnly();
+ return const_cast(EmuConfig.Trace);
+}
+
// This function should be called once during program execution.
void SysDetect()
@@ -146,23 +167,21 @@ SysCoreAllocations::SysCoreAllocations()
Console.WriteLn( "Allocating memory for recompilers..." );
- try
- {
+ try {
recCpu.Allocate();
RecSuccess_EE = true;
}
- catch( Exception::BaseException& ex )
+ catch( Exception::RuntimeError& ex )
{
Console.Error( L"EE Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
recCpu.Shutdown();
}
- try
- {
+ try {
psxRec.Allocate();
RecSuccess_IOP = true;
}
- catch( Exception::BaseException& ex )
+ catch( Exception::RuntimeError& ex )
{
Console.Error( L"IOP Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
psxRec.Shutdown();
@@ -170,23 +189,21 @@ SysCoreAllocations::SysCoreAllocations()
// hmm! : VU0 and VU1 pre-allocations should do sVU and mVU separately? Sounds complicated. :(
- try
- {
+ try {
VU0micro::recAlloc();
RecSuccess_VU0 = true;
}
- catch( Exception::BaseException& ex )
+ catch( Exception::RuntimeError& ex )
{
Console.Error( L"VU0 Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
VU0micro::recShutdown();
}
- try
- {
+ try {
VU1micro::recAlloc();
RecSuccess_VU1 = true;
}
- catch( Exception::BaseException& ex )
+ catch( Exception::RuntimeError& ex )
{
Console.Error( L"VU1 Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
VU1micro::recShutdown();
@@ -239,8 +256,8 @@ bool SysCoreAllocations::HadSomeFailures( const Pcsx2Config::RecompilerOptions&
// Use this method to reset the recs when important global pointers like the MTGS are re-assigned.
void SysClearExecutionCache()
{
- Cpu = CHECK_EEREC ? &recCpu : &intCpu;
- psxCpu = CHECK_IOPREC ? &psxRec : &psxInt;
+ Cpu = CHECK_EEREC ? &recCpu : &intCpu;
+ psxCpu = CHECK_IOPREC ? &psxRec : &psxInt;
Cpu->Reset();
psxCpu->Reset();
diff --git a/pcsx2/System.h b/pcsx2/System.h
index c76286ba08..3da30065a1 100644
--- a/pcsx2/System.h
+++ b/pcsx2/System.h
@@ -53,6 +53,9 @@ protected:
void CleanupMess() throw();
};
+// GetSysCoreAlloc - this function is not implemented by PCSX2 core -- it must be
+// implemented by the provisioning interface.
+extern SysCoreAllocations& GetSysCoreAlloc();
extern void SysDetect(); // Detects cpu type and fills cpuInfo structs.
extern void SysClearExecutionCache(); // clears recompiled execution caches!
diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp
index ae5683133f..a4e5810166 100644
--- a/pcsx2/System/SysCoreThread.cpp
+++ b/pcsx2/System/SysCoreThread.cpp
@@ -16,6 +16,7 @@
#include "PrecompiledHeader.h"
#include "Common.h"
+#include "Counters.h"
#include "GS.h"
#include "Elfheader.h"
#include "PageFaultSource.h"
@@ -40,6 +41,7 @@ SysCoreThread::SysCoreThread()
m_name = L"EE Core";
m_resetRecompilers = true;
m_resetProfilers = true;
+ m_resetVsyncTimers = true;
m_resetVirtualMachine = true;
m_hasValidState = false;
}
@@ -106,6 +108,14 @@ ScopedCoreThreadSuspend::ScopedCoreThreadSuspend()
m_ResumeWhenDone = GetCoreThread().Suspend();
}
+ScopedCoreThreadSuspend::~ScopedCoreThreadSuspend() throw()
+{
+ if( m_ResumeWhenDone )
+ {
+ Console.WriteLn( Color_Gray, "Scoped CoreThread suspend was not allowed to resume." );
+ }
+}
+
// Resumes CoreThread execution, but *only* if it was in a running state when this object
// was instanized. Subsequent calls to Resume() will be ignored.
void ScopedCoreThreadSuspend::Resume()
@@ -115,14 +125,29 @@ void ScopedCoreThreadSuspend::Resume()
m_ResumeWhenDone = false;
}
-ScopedCoreThreadSuspend::~ScopedCoreThreadSuspend() throw()
+ScopedCoreThreadPause::ScopedCoreThreadPause()
+{
+ m_ResumeWhenDone = GetCoreThread().Pause();
+}
+
+ScopedCoreThreadPause::~ScopedCoreThreadPause() throw()
{
if( m_ResumeWhenDone )
{
- Console.WriteLn( Color_Gray, "Scoped CoreThread suspend was not allowed to resume." );
+ Console.WriteLn( Color_Gray, "Scoped CoreThread pause was not allowed to resume." );
}
}
+// Resumes CoreThread execution, but *only* if it was in a running state when this object
+// was instanized. Subsequent calls to Resume() will be ignored.
+void ScopedCoreThreadPause::Resume()
+{
+ if( m_ResumeWhenDone )
+ GetCoreThread().Resume();
+ m_ResumeWhenDone = false;
+}
+
+
// Applies a full suite of new settings, which will automatically facilitate the necessary
// resets of the core and components (including plugins, if needed). The scope of resetting
// is determined by comparing the current settings against the new settings, so that only
@@ -131,12 +156,14 @@ void SysCoreThread::ApplySettings( const Pcsx2Config& src )
{
if( src == EmuConfig ) return;
- ScopedCoreThreadSuspend suspend_core;
+ ScopedCoreThreadPause sys_paused;
m_resetRecompilers = ( src.Cpu != EmuConfig.Cpu ) || ( src.Gamefixes != EmuConfig.Gamefixes ) || ( src.Speedhacks != EmuConfig.Speedhacks );
- m_resetProfilers = (src.Profiler != EmuConfig.Profiler );
-
+ m_resetProfilers = ( src.Profiler != EmuConfig.Profiler );
+ m_resetVsyncTimers = ( src.GS != EmuConfig.GS );
+
const_cast(EmuConfig) = src;
+ sys_paused.Resume();
}
void SysCoreThread::ChangeCdvdSource( CDVD_SourceType type )
@@ -189,11 +216,7 @@ void SysCoreThread::CpuInitializeMess()
{
if( m_hasValidState ) return;
- // Some recompiler mess might be left over -- nuke it here:
- SysClearExecutionCache();
- memBindConditionalHandlers();
- m_resetRecompilers = false;
- m_resetProfilers = false;
+ _reset_stuff_as_needed();
ScopedBool_ClearOnError sbcoe( m_hasValidState );
@@ -238,13 +261,8 @@ void SysCoreThread::CpuInitializeMess()
sbcoe.Success();
}
-void SysCoreThread::StateCheckInThread()
+void SysCoreThread::_reset_stuff_as_needed()
{
- GetMTGS().RethrowException();
- _parent::StateCheckInThread();
- if( !m_hasValidState )
- throw Exception::RuntimeError( "Invalid emulation state detected; Virtual machine threads have been cancelled." );
-
if( m_resetRecompilers || m_resetProfilers )
{
SysClearExecutionCache();
@@ -252,6 +270,23 @@ void SysCoreThread::StateCheckInThread()
m_resetRecompilers = false;
m_resetProfilers = false;
}
+
+ if( m_resetVsyncTimers )
+ {
+ UpdateVSyncRate();
+ frameLimitReset();
+ m_resetVsyncTimers = false;
+ }
+}
+
+void SysCoreThread::StateCheckInThread()
+{
+ GetMTGS().RethrowException();
+ _parent::StateCheckInThread();
+ if( !m_hasValidState )
+ throw Exception::RuntimeError( "Invalid emulation state detected; Virtual machine threads have been cancelled." );
+
+ _reset_stuff_as_needed();
}
void SysCoreThread::ExecuteTaskInThread()
diff --git a/pcsx2/System/SysThreads.h b/pcsx2/System/SysThreads.h
index 32663571e9..79a4ae5ca8 100644
--- a/pcsx2/System/SysThreads.h
+++ b/pcsx2/System/SysThreads.h
@@ -187,6 +187,7 @@ class SysCoreThread : public SysThreadBase
protected:
bool m_resetRecompilers;
bool m_resetProfilers;
+ bool m_resetVsyncTimers;
bool m_resetVirtualMachine;
bool m_hasValidState;
@@ -223,6 +224,7 @@ public:
protected:
void CpuInitializeMess();
+ void _reset_stuff_as_needed();
virtual void Start();
virtual void OnSuspendInThread();
@@ -252,8 +254,17 @@ struct ScopedCoreThreadSuspend
bool m_ResumeWhenDone;
ScopedCoreThreadSuspend();
- void Resume();
virtual ~ScopedCoreThreadSuspend() throw();
+ virtual void Resume();
+};
+
+struct ScopedCoreThreadPause
+{
+ bool m_ResumeWhenDone;
+
+ ScopedCoreThreadPause();
+ virtual ~ScopedCoreThreadPause() throw();
+ virtual void Resume();
};
// GetCoreThread() is a required external implementation. This function is *NOT*
diff --git a/pcsx2/VU0microInterp.cpp b/pcsx2/VU0microInterp.cpp
index 5b4b6256db..7adca3a0e1 100644
--- a/pcsx2/VU0microInterp.cpp
+++ b/pcsx2/VU0microInterp.cpp
@@ -240,4 +240,6 @@ const VUmicroCpu intVU0 =
, intStep
, intExecuteBlock
, intClear
+
+, true
};
diff --git a/pcsx2/VU1microInterp.cpp b/pcsx2/VU1microInterp.cpp
index 1822fa53e5..5a06a0893f 100644
--- a/pcsx2/VU1microInterp.cpp
+++ b/pcsx2/VU1microInterp.cpp
@@ -225,4 +225,6 @@ const VUmicroCpu intVU1 =
, intStep
, intExecuteBlock
, intClear
+
+, true
};
diff --git a/pcsx2/VUmicro.h b/pcsx2/VUmicro.h
index c9df69d6a9..766050c6f8 100644
--- a/pcsx2/VUmicro.h
+++ b/pcsx2/VUmicro.h
@@ -23,6 +23,10 @@ struct VUmicroCpu
void (*Step)();
void (*ExecuteBlock)(); // VUs should support block-level execution only.
void (__fastcall *Clear)(u32 Addr, u32 Size);
+
+ // this boolean indicates to some generic logging facilities if the VU's registers
+ // are valid for logging or not. (see DisVU1Micro.cpp, etc)
+ bool IsInterpreter;
};
extern VUmicroCpu CpuVU0;
diff --git a/pcsx2/VUmicroMem.cpp b/pcsx2/VUmicroMem.cpp
index c41deb95da..777a64f427 100644
--- a/pcsx2/VUmicroMem.cpp
+++ b/pcsx2/VUmicroMem.cpp
@@ -42,15 +42,7 @@ static const uint m_vuMemSize =
0x1000 + // VU0micro memory
0x4000+0x800 + // VU0 memory and VU1 registers
0x4000 + // VU1 memory
- 0x4000;/* + // VU1micro memory
- 0x4000; */ // HACKFIX (see below)
-
-// HACKFIX! (air)
-// The VIFdma1 has a nasty habit of transferring data into the 4k page of memory above
-// the VU1. (oops!!) This happens to be recLUT most of the time, which causes rapid death
-// of our emulator. So we allocate some extra space here to keep VIF1 a little happier.
-
-// fixme - When the VIF is fixed, remove the third +0x4000 above. :)
+ 0x4000;
void vuMicroMemAlloc()
{
diff --git a/pcsx2/gui/AppConfig.cpp b/pcsx2/gui/AppConfig.cpp
index 9134c0fecb..8d18c17e04 100644
--- a/pcsx2/gui/AppConfig.cpp
+++ b/pcsx2/gui/AppConfig.cpp
@@ -399,14 +399,19 @@ void AppConfig::LoadSave( IniInterface& ini )
LoadSaveMemcards( ini );
// Process various sub-components:
- ProgLogBox.LoadSave( ini, L"ProgramLog" );
- Ps2ConBox.LoadSave( ini, L"Ps2Console" );
+ ProgLogBox .LoadSave( ini, L"ProgramLog" );
+ Ps2ConBox .LoadSave( ini, L"Ps2Console" );
- Folders.LoadSave( ini );
- BaseFilenames.LoadSave( ini );
+ Folders .LoadSave( ini );
+ BaseFilenames .LoadSave( ini );
+ GSWindow .LoadSave( ini );
+
+ // Load Emulation options and apply some defaults overtop saved items, which are regulated
+ // by the PCSX2 UI.
EmuOptions.LoadSave( ini );
- GSWindow.LoadSave( ini );
+ if( ini.IsLoading() )
+ EmuOptions.GS.LimitScalar = GSWindow.NominalScalar;
ini.Flush();
}
@@ -444,18 +449,18 @@ void AppConfig::FolderOptions::ApplyDefaults()
}
// ------------------------------------------------------------------------
-AppConfig::FolderOptions::FolderOptions() :
- bitset( 0xffffffff )
-, Plugins ( PathDefs::GetPlugins() )
-, Bios ( PathDefs::GetBios() )
-, Snapshots ( PathDefs::GetSnapshots() )
-, Savestates ( PathDefs::GetSavestates() )
-, MemoryCards ( PathDefs::GetMemoryCards() )
-, Logs ( PathDefs::GetLogs() )
+AppConfig::FolderOptions::FolderOptions()
+ : Plugins ( PathDefs::GetPlugins() )
+ , Bios ( PathDefs::GetBios() )
+ , Snapshots ( PathDefs::GetSnapshots() )
+ , Savestates ( PathDefs::GetSavestates() )
+ , MemoryCards ( PathDefs::GetMemoryCards() )
+ , Logs ( PathDefs::GetLogs() )
-, RunIso( PathDefs::GetDocuments() ) // raw default is always the Documents folder.
-, RunELF( PathDefs::GetDocuments() ) // raw default is always the Documents folder.
+ , RunIso( PathDefs::GetDocuments() ) // raw default is always the Documents folder.
+ , RunELF( PathDefs::GetDocuments() ) // raw default is always the Documents folder.
{
+ bitset = 0xffffffff;
}
void AppConfig::FolderOptions::LoadSave( IniInterface& ini )
@@ -518,8 +523,12 @@ void AppConfig::FilenameOptions::LoadSave( IniInterface& ini )
}
// ------------------------------------------------------------------------
-AppConfig::GSOptions::GSOptions()
+AppConfig::GSWindowOptions::GSWindowOptions()
{
+ NominalScalar = 1.0;
+ TurboScalar = 3.0;
+ SlomoScalar = 0.33;
+
CloseOnEsc = true;
DefaultToFullscreen = false;
AlwaysHideMouse = false;
@@ -532,10 +541,14 @@ AppConfig::GSOptions::GSOptions()
IsMaximized = false;
}
-void AppConfig::GSOptions::SanityCheck()
+void AppConfig::GSWindowOptions::SanityCheck()
{
// Ensure Conformation of various options...
+ NominalScalar .ConfineTo( 0.05, 10.0 );
+ TurboScalar .ConfineTo( 0.05, 10.0 );
+ SlomoScalar .ConfineTo( 0.05, 10.0 );
+
WindowSize.x = std::max( WindowSize.x, 8 );
WindowSize.x = std::min( WindowSize.x, wxGetDisplayArea().GetWidth()-16 );
@@ -550,12 +563,15 @@ void AppConfig::GSOptions::SanityCheck()
AspectRatio = AspectRatio_4_3;
}
-void AppConfig::GSOptions::LoadSave( IniInterface& ini )
+void AppConfig::GSWindowOptions::LoadSave( IniInterface& ini )
{
IniScopedGroup path( ini, L"GSWindow" );
-
- GSOptions defaults;
-
+ GSWindowOptions defaults;
+
+ IniEntry( NominalScalar );
+ IniEntry( TurboScalar );
+ IniEntry( SlomoScalar );
+
IniEntry( CloseOnEsc );
IniEntry( DefaultToFullscreen );
IniEntry( AlwaysHideMouse );
@@ -573,7 +589,7 @@ void AppConfig::GSOptions::LoadSave( IniInterface& ini )
ini.EnumEntry( L"AspectRatio", AspectRatio, AspectRatioNames, defaults.AspectRatio );
- DisableResizeBorders = false;
+ if( ini.IsLoading() ) SanityCheck();
}
wxFileConfig* OpenFileConfig( const wxString& filename )
diff --git a/pcsx2/gui/AppConfig.h b/pcsx2/gui/AppConfig.h
index a498c1f80f..8eb272bbc2 100644
--- a/pcsx2/gui/AppConfig.h
+++ b/pcsx2/gui/AppConfig.h
@@ -120,7 +120,7 @@ public:
// ------------------------------------------------------------------------
// The GS window receives much love from the land of Options and Settings.
//
- struct GSOptions
+ struct GSWindowOptions
{
// Closes the GS/Video port on escape (good for fullscreen activity)
bool CloseOnEsc;
@@ -129,12 +129,16 @@ public:
bool DisableResizeBorders;
AspectRatioType AspectRatio;
-
+
wxSize WindowSize;
wxPoint WindowPos;
bool IsMaximized;
- GSOptions();
+ Fixed100 NominalScalar;
+ Fixed100 TurboScalar;
+ Fixed100 SlomoScalar;
+
+ GSWindowOptions();
void LoadSave( IniInterface& conf );
void SanityCheck();
@@ -183,7 +187,7 @@ public:
ConsoleLogOptions Ps2ConBox;
FolderOptions Folders;
FilenameOptions BaseFilenames;
- GSOptions GSWindow;
+ GSWindowOptions GSWindow;
// PCSX2-core emulation options, which are passed to the emu core prior to initiating
// an emulation session. Note these are the options saved into the GUI ini file and
diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp
index b70089c980..b386f1b41a 100644
--- a/pcsx2/gui/AppCoreThread.cpp
+++ b/pcsx2/gui/AppCoreThread.cpp
@@ -192,9 +192,6 @@ void AppCoreThread::StateCheckInThread()
case WXK_MENU: m_kevt.m_altDown = isDown; return;
}
- /*if( vkey != WXK_ALT )
- Console.Warning( "It's not Alt!" );*/
-
m_kevt.m_keyCode = vkey;
wxGetApp().PostPadKey( m_kevt );
}
diff --git a/pcsx2/gui/AppInit.cpp b/pcsx2/gui/AppInit.cpp
index 0d438353f7..21e2169118 100644
--- a/pcsx2/gui/AppInit.cpp
+++ b/pcsx2/gui/AppInit.cpp
@@ -306,25 +306,21 @@ bool Pcsx2App::OnInit()
if( !m_CoreAllocs->RecSuccess_EE )
{
message += L"\t* R5900 (EE)\n";
- g_Session.ForceDisableEErec = true;
}
if( !m_CoreAllocs->RecSuccess_IOP )
{
message += L"\t* R3000A (IOP)\n";
- g_Session.ForceDisableIOPrec = true;
}
if( !m_CoreAllocs->RecSuccess_VU0 )
{
message += L"\t* VU0\n";
- g_Session.ForceDisableVU0rec = true;
}
if( !m_CoreAllocs->RecSuccess_VU1 )
{
message += L"\t* VU1\n";
- g_Session.ForceDisableVU1rec = true;
}
message += pxE( ".Popup Error:EmuCore:MemoryForRecs",
diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp
index 4f3526ec88..13e277377f 100644
--- a/pcsx2/gui/AppMain.cpp
+++ b/pcsx2/gui/AppMain.cpp
@@ -435,17 +435,18 @@ void AppApplySettings( const AppConfig* oldconf )
int toSend = 0;
sApp.Source_SettingsApplied().Dispatch( toSend );
+ suspend_core.Resume();
}
static wxFileConfig _dud_config;
-AppIniSaver::AppIniSaver() :
- IniSaver( (GetAppConfig() != NULL) ? *GetAppConfig() : _dud_config )
+AppIniSaver::AppIniSaver()
+ : IniSaver( (GetAppConfig() != NULL) ? *GetAppConfig() : _dud_config )
{
}
-AppIniLoader::AppIniLoader() :
- IniLoader( (GetAppConfig() != NULL) ? *GetAppConfig() : _dud_config )
+AppIniLoader::AppIniLoader()
+ : IniLoader( (GetAppConfig() != NULL) ? *GetAppConfig() : _dud_config )
{
}
@@ -656,3 +657,8 @@ SysMtgsThread& GetMTGS()
{
return mtgsThread;
}
+
+SysCoreAllocations& GetSysCoreAlloc()
+{
+ return *wxGetApp().m_CoreAllocs;
+}
diff --git a/pcsx2/gui/FrameForGS.cpp b/pcsx2/gui/FrameForGS.cpp
index 912144ff15..df2a97a22b 100644
--- a/pcsx2/gui/FrameForGS.cpp
+++ b/pcsx2/gui/FrameForGS.cpp
@@ -48,13 +48,14 @@ GSPanel::GSPanel( wxWindow* parent )
: wxWindow()
, m_Listener_SettingsApplied( wxGetApp().Source_SettingsApplied(), EventListener ( this, OnSettingsApplied ) )
, m_HideMouseTimer( this )
-
{
m_CursorShown = true;
if ( !wxWindow::Create(parent, wxID_ANY) )
throw Exception::RuntimeError( "GSPanel constructor esplode!!" );
+ SetName( L"GSPanel" );
+
InitDefaultAccelerators();
if( g_Conf->GSWindow.AlwaysHideMouse )
@@ -115,7 +116,7 @@ void GSPanel::DoResize()
if( client.x/16 <= client.y/9 )
viewport.y = (int)(client.x * (9.0/16.0));
else
- viewport.x = (int)(client.y * (9.0/16.0));
+ viewport.x = (int)(client.y * (16.0/9.0));
break;
}
@@ -182,6 +183,10 @@ void __evt_fastcall GSPanel::OnSettingsApplied( void* obj, int& evt )
panel->DoShowMouse();
}
+// --------------------------------------------------------------------------------------
+// GSFrame
+// --------------------------------------------------------------------------------------
+
GSFrame::GSFrame(wxWindow* parent, const wxString& title)
: wxFrame(parent, wxID_ANY, title,
g_Conf->GSWindow.WindowPos, wxSize( 640, 480 ),
@@ -193,11 +198,12 @@ GSFrame::GSFrame(wxWindow* parent, const wxString& title)
SetClientSize( g_Conf->GSWindow.WindowSize );
- m_gspanel = new GSPanel( this );
+ m_gspanel = new GSPanel( this );
- //Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler (GSFrame::OnCloseWindow) );
- Connect( wxEVT_MOVE, wxMoveEventHandler (GSFrame::OnMove) );
- Connect( wxEVT_SIZE, wxSizeEventHandler (GSFrame::OnResize) );
+ //Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler (GSFrame::OnCloseWindow) );
+ Connect( wxEVT_MOVE, wxMoveEventHandler (GSFrame::OnMove) );
+ Connect( wxEVT_SIZE, wxSizeEventHandler (GSFrame::OnResize) );
+ Connect( wxEVT_ACTIVATE, wxActivateEventHandler (GSFrame::OnActivate) );
}
GSFrame::~GSFrame() throw()
@@ -210,6 +216,12 @@ wxWindow* GSFrame::GetViewport()
return m_gspanel;
}
+void GSFrame::OnActivate( wxActivateEvent& evt )
+{
+ evt.Skip();
+ if( wxWindow* gsPanel = FindWindowByName(L"GSPanel") ) gsPanel->SetFocus();
+}
+
void GSFrame::OnMove( wxMoveEvent& evt )
{
// evt.GetPosition() returns the client area position, not the window frame position.
@@ -227,7 +239,15 @@ void GSFrame::OnMove( wxMoveEvent& evt )
void GSFrame::OnResize( wxSizeEvent& evt )
{
g_Conf->GSWindow.WindowSize = GetClientSize();
- m_gspanel->DoResize();
+
+ if( GSPanel* gsPanel = (GSPanel*)FindWindowByName(L"GSPanel") )
+ {
+ gsPanel->DoResize();
+ gsPanel->SetFocus();
+ }
+
+ //wxPoint hudpos = wxPoint(-10,-10) + (GetClientSize() - m_hud->GetSize());
+ //m_hud->SetPosition( hudpos ); //+ GetScreenPosition() + GetClientAreaOrigin() );
// if we skip, the panel is auto-sized to fit our window anyway, which we do not want!
//evt.Skip();
diff --git a/pcsx2/gui/GlobalCommands.cpp b/pcsx2/gui/GlobalCommands.cpp
index 0505228c8c..b5b999be50 100644
--- a/pcsx2/gui/GlobalCommands.cpp
+++ b/pcsx2/gui/GlobalCommands.cpp
@@ -53,24 +53,87 @@ wxString KeyAcceleratorCode::ToString() const
).ToString();
}
-int limitOn = false;
+enum LimiterModeType
+{
+ Limit_Nominal,
+ Limit_Turbo,
+ Limit_Slomo,
+};
+
+static LimiterModeType g_LimiterMode = Limit_Nominal;
+
namespace Implementations
{
void Frameskip_Toggle()
{
- limitOn ^= 1;
- Console.WriteLn("Framelimit mode changed to %d", limitOn ? 1 : 0);
- // FIXME : Reimplement framelimiting using new double-switch boolean system
+ g_Conf->EmuOptions.GS.FrameSkipEnable = !g_Conf->EmuOptions.GS.FrameSkipEnable;
+ SetGSConfig().FrameSkipEnable = g_Conf->EmuOptions.GS.FrameSkipEnable;
+
+ if( EmuConfig.GS.FrameSkipEnable )
+ Console.WriteLn( "(FrameSkipping) Enabled : FrameDraws=%d, FrameSkips=%d", g_Conf->EmuOptions.GS.ConsecutiveFrames, g_Conf->EmuOptions.GS.ConsecutiveSkip );
+ else
+ Console.WriteLn( "(FrameSkipping) Disabled." );
}
void Framelimiter_TurboToggle()
{
- limitOn ^= 1;
- Console.WriteLn("Framelimit mode changed to %d", limitOn ? 1 : 0);
+ if( !g_Conf->EmuOptions.GS.FrameLimitEnable )
+ {
+ Console.WriteLn( "(FrameLimiter) Turbo toggle ignored; framelimiter is currently disabled." );
+ return;
+ }
+
+ ScopedCoreThreadPause pauser;
+ if( g_LimiterMode == Limit_Turbo )
+ {
+ GSsetVsync( g_Conf->EmuOptions.GS.VsyncEnable );
+ g_LimiterMode = Limit_Nominal;
+ g_Conf->EmuOptions.GS.LimitScalar = g_Conf->GSWindow.NominalScalar;
+ Console.WriteLn("(FrameLimiter) Turbo DISABLED." );
+ }
+ else
+ {
+ GSsetVsync( false );
+ g_LimiterMode = Limit_Turbo;
+ g_Conf->EmuOptions.GS.LimitScalar = g_Conf->GSWindow.TurboScalar;
+ Console.WriteLn("(FrameLimiter) Turbo ENABLED." );
+ }
+ pauser.Resume();
+ }
+
+ void Framelimiter_SlomoToggle()
+ {
+ // Slow motion auto-enables the framelimiter even if it's disabled.
+ // This seems like desirable and expected behavior.
+
+ // FIXME: Inconsistent use of g_Conf->EmuOptions vs. EmuConfig. Should figure
+ // out a better consistency approach... -air
+
+ ScopedCoreThreadPause pauser;
+ GSsetVsync( g_Conf->EmuOptions.GS.VsyncEnable );
+ if( g_LimiterMode == Limit_Slomo )
+ {
+ g_LimiterMode = Limit_Nominal;
+ g_Conf->EmuOptions.GS.LimitScalar = g_Conf->GSWindow.NominalScalar;
+ Console.WriteLn("(FrameLimiter) SlowMotion DISABLED." );
+ }
+ else
+ {
+ g_LimiterMode = Limit_Slomo;
+ g_Conf->EmuOptions.GS.LimitScalar = g_Conf->GSWindow.SlomoScalar;
+ Console.WriteLn("(FrameLimiter) SlowMotion ENABLED." );
+ g_Conf->EmuOptions.GS.FrameLimitEnable = true;
+ }
+ pauser.Resume();
}
void Framelimiter_MasterToggle()
{
+ ScopedCoreThreadPause pauser;
+ g_Conf->EmuOptions.GS.FrameLimitEnable = !g_Conf->EmuOptions.GS.FrameLimitEnable;
+ GSsetVsync( g_Conf->EmuOptions.GS.FrameLimitEnable && g_Conf->EmuOptions.GS.VsyncEnable );
+ Console.WriteLn("(FrameLimiter) %s.", g_Conf->EmuOptions.GS.FrameLimitEnable ? "ENABLED" : "DISABLED" );
+ pauser.Resume();
}
void Sys_Suspend()
@@ -104,7 +167,7 @@ namespace Implementations
// FIXME: Some of the trace logs will require recompiler resets to be activated properly.
// But since those haven't been implemented yet, no point in implementing that here either.
- const_cast(EmuConfig).Trace.Enabled = !EmuConfig.Trace.Enabled;
+ SetTraceConfig().Enabled = !EmuConfig.Trace.Enabled;
GSprintf(10, const_cast(EmuConfig.Trace.Enabled ? "Logging Enabled." : "Logging Disabled."));
}
@@ -209,6 +272,12 @@ static const GlobalCommandDescriptor CommandDeclarations[] =
NULL,
},
+ { "Framelimiter_SlomoToggle",
+ Implementations::Framelimiter_TurboToggle,
+ NULL,
+ NULL,
+ },
+
{ "Framelimiter_MasterToggle",
Implementations::Framelimiter_MasterToggle,
NULL,
@@ -314,9 +383,10 @@ void Pcsx2App::InitDefaultGlobalAccelerators()
GlobalAccels.Map( AAC( WXK_F2 ), "States_CycleSlotForward" );
GlobalAccels.Map( AAC( WXK_F2 ).Shift(), "States_CycleSlotBackward" );
- GlobalAccels.Map( AAC( WXK_F4 ), "Frameskip_Toggle");
+ GlobalAccels.Map( AAC( WXK_F4 ), "Framelimiter_MasterToggle");
+ GlobalAccels.Map( AAC( WXK_F4 ).Shift(), "Frameskip_Toggle");
GlobalAccels.Map( AAC( WXK_TAB ), "Framelimiter_TurboToggle" );
- GlobalAccels.Map( AAC( WXK_TAB ).Shift(), "Framelimiter_MasterToggle" );
+ GlobalAccels.Map( AAC( WXK_TAB ).Shift(), "Framelimiter_SlomoToggle" );
// Hack! The following bindings are temporary hacks which are needed because of issues
// with PAD plugin interfacing (the local window-based accelerators in GSPanel are
diff --git a/pcsx2/gui/IniInterface.cpp b/pcsx2/gui/IniInterface.cpp
index 6ba10bf4d5..70ffce709b 100644
--- a/pcsx2/gui/IniInterface.cpp
+++ b/pcsx2/gui/IniInterface.cpp
@@ -141,6 +141,16 @@ int IniLoader::EntryBitfield( const wxString& var, int value, const int defvalue
return result;
}
+void IniLoader::Entry( const wxString& var, Fixed100& value, const Fixed100& defvalue )
+{
+ // Note: the "easy" way would be to convert to double and load/save that, but floating point
+ // has way too much rounding error so we really need to do things out manually.. >_<
+
+ wxString readval( value.ToString() );
+ m_Config.Read( var, &readval );
+ value = Fixed100::FromString( readval, value );
+}
+
void IniLoader::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue )
{
TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue );
@@ -241,6 +251,14 @@ int IniSaver::EntryBitfield( const wxString& var, int value, const int defvalue
return value;
}
+void IniSaver::Entry( const wxString& var, Fixed100& value, const Fixed100& defvalue )
+{
+ // Note: the "easy" way would be to convert to double and load/save that, but floating point
+ // has way too much rounding error so we really need to do things out manually, using strings.
+
+ m_Config.Write( var, value.ToString() );
+}
+
void IniSaver::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue )
{
m_Config.Write( var, ToString( value ) );
diff --git a/pcsx2/gui/IniInterface.h b/pcsx2/gui/IniInterface.h
index 0e3fa534a4..84b7021eb8 100644
--- a/pcsx2/gui/IniInterface.h
+++ b/pcsx2/gui/IniInterface.h
@@ -55,6 +55,8 @@ public:
virtual bool EntryBitBool( const wxString& var, bool value, const bool defvalue=false )=0;
virtual int EntryBitfield( const wxString& var, int value, const int defvalue=0 )=0;
+ virtual void Entry( const wxString& var, Fixed100& value, const Fixed100& defvalue=Fixed100() )=0;
+
virtual void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition )=0;
virtual void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize )=0;
virtual void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect )=0;
@@ -113,6 +115,8 @@ public:
bool EntryBitBool( const wxString& var, bool value, const bool defvalue=false );
int EntryBitfield( const wxString& var, int value, const int defvalue=0 );
+ void Entry( const wxString& var, Fixed100& value, const Fixed100& defvalue=Fixed100() );
+
void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition );
void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize );
void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect );
@@ -148,6 +152,8 @@ public:
bool EntryBitBool( const wxString& var, bool value, const bool defvalue=false );
int EntryBitfield( const wxString& var, int value, const int defvalue=0 );
+ void Entry( const wxString& var, Fixed100& value, const Fixed100& defvalue=Fixed100() );
+
void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition );
void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize );
void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect );
diff --git a/pcsx2/gui/MainFrame.h b/pcsx2/gui/MainFrame.h
index d4476ba8e1..d22a7ffa44 100644
--- a/pcsx2/gui/MainFrame.h
+++ b/pcsx2/gui/MainFrame.h
@@ -68,6 +68,7 @@ public:
protected:
void OnMove( wxMoveEvent& evt );
void OnResize( wxSizeEvent& evt );
+ void OnActivate( wxActivateEvent& evt );
};
struct PluginMenuAddition
diff --git a/pcsx2/gui/Panels/VideoPanel.cpp b/pcsx2/gui/Panels/VideoPanel.cpp
index b5fd64c83d..b22da54261 100644
--- a/pcsx2/gui/Panels/VideoPanel.cpp
+++ b/pcsx2/gui/Panels/VideoPanel.cpp
@@ -260,17 +260,17 @@ Panels::VideoPanel::VideoPanel( wxWindow* parent ) :
*this += s_table | pxExpand;
- m_check_SynchronousGS->SetValue( g_Conf->EmuOptions.Video.SynchronousMTGS );
+ m_check_SynchronousGS->SetValue( g_Conf->EmuOptions.GS.SynchronousMTGS );
}
void Panels::VideoPanel::Apply()
{
- g_Conf->EmuOptions.Video.SynchronousMTGS = m_check_SynchronousGS->GetValue();
+ g_Conf->EmuOptions.GS.SynchronousMTGS = m_check_SynchronousGS->GetValue();
}
void Panels::GSWindowSettingsPanel::OnSettingsChanged()
{
- const AppConfig::GSOptions& conf( g_Conf->GSWindow );
+ const AppConfig::GSWindowOptions& conf( g_Conf->GSWindow );
m_check_CloseGS ->SetValue( conf.CloseOnEsc );
m_check_Fullscreen ->SetValue( conf.DefaultToFullscreen );
@@ -279,6 +279,8 @@ void Panels::GSWindowSettingsPanel::OnSettingsChanged()
m_combo_AspectRatio ->SetSelection( (int)conf.AspectRatio );
+ m_check_VsyncEnable ->SetValue( g_Conf->EmuOptions.GS.VsyncEnable );
+
m_text_WindowWidth ->SetValue( wxsFormat( L"%d", conf.WindowSize.GetWidth() ) );
m_text_WindowHeight ->SetValue( wxsFormat( L"%d", conf.WindowSize.GetHeight() ) );
@@ -286,14 +288,17 @@ void Panels::GSWindowSettingsPanel::OnSettingsChanged()
void Panels::GSWindowSettingsPanel::Apply()
{
- AppConfig::GSOptions& gsopt( g_Conf->GSWindow );
-
- gsopt.CloseOnEsc = m_check_CloseGS ->GetValue();
- gsopt.DefaultToFullscreen = m_check_Fullscreen->GetValue();
- gsopt.AlwaysHideMouse = m_check_HideMouse ->GetValue();
- gsopt.DisableResizeBorders = m_check_SizeLock ->GetValue();
+ AppConfig::GSWindowOptions& appconf( g_Conf->GSWindow );
+ Pcsx2Config::GSOptions& gsconf( g_Conf->EmuOptions.GS );
- gsopt.AspectRatio = (AspectRatioType)m_combo_AspectRatio->GetSelection();
+ appconf.CloseOnEsc = m_check_CloseGS ->GetValue();
+ appconf.DefaultToFullscreen = m_check_Fullscreen->GetValue();
+ appconf.AlwaysHideMouse = m_check_HideMouse ->GetValue();
+ appconf.DisableResizeBorders = m_check_SizeLock ->GetValue();
+
+ appconf.AspectRatio = (AspectRatioType)m_combo_AspectRatio->GetSelection();
+
+ gsconf.VsyncEnable = m_check_VsyncEnable->GetValue();
long xr, yr;
@@ -303,21 +308,43 @@ void Panels::GSWindowSettingsPanel::Apply()
_("Invalid window dimensions specified: Size cannot contain non-numeric digits! >_<")
);
- gsopt.WindowSize.x = xr;
- gsopt.WindowSize.y = yr;
+ appconf.WindowSize.x = xr;
+ appconf.WindowSize.y = yr;
}
void Panels::FramelimiterPanel::OnSettingsChanged()
{
- const Pcsx2Config::VideoOptions& conf( g_Conf->EmuOptions.Video );
+ const AppConfig::GSWindowOptions& appconf( g_Conf->GSWindow );
+ const Pcsx2Config::GSOptions& gsconf( g_Conf->EmuOptions.GS );
- // TODO : Apply options from config *to* checkboxes (once video config struct is implemented)
+ m_check_LimiterDisable->SetValue( !gsconf.FrameLimitEnable );
+
+ m_spin_NominalPct ->SetValue( (appconf.NominalScalar * 100).ToIntRounded() );
+ m_spin_TurboPct ->SetValue( (appconf.TurboScalar * 100).ToIntRounded() );
+ m_spin_TurboPct ->SetValue( (appconf.SlomoScalar * 100).ToIntRounded() );
+
+ m_text_BaseNtsc ->SetValue( gsconf.FramerateNTSC.ToString() );
+ m_text_BasePal ->SetValue( gsconf.FrameratePAL.ToString() );
}
void Panels::FramelimiterPanel::Apply()
{
- Pcsx2Config::VideoOptions& conf( g_Conf->EmuOptions.Video );
+ AppConfig::GSWindowOptions& appconf( g_Conf->GSWindow );
+ Pcsx2Config::GSOptions& gsconf( g_Conf->EmuOptions.GS );
- // TODO : Apply options from checkboxes (once video config struct is is implemented)
+ gsconf.FrameLimitEnable = !m_check_LimiterDisable->GetValue();
+
+ appconf.NominalScalar = m_spin_NominalPct ->GetValue();
+ appconf.TurboScalar = m_spin_TurboPct ->GetValue();
+ appconf.SlomoScalar = m_spin_SlomoPct ->GetValue();
+
+ double ntsc, pal;
+ if( !m_text_BaseNtsc->GetValue().ToDouble( &ntsc ) ||
+ !m_text_BasePal ->GetValue().ToDouble( &pal )
+ )
+ throw Exception::CannotApplySettings( this, wxLt("Error while parsing either NTSC or PAL framerate settings. Settings must be valid floating point numerics.") );
+
+ gsconf.FramerateNTSC = ntsc;
+ gsconf.FrameratePAL = pal;
}
diff --git a/pcsx2/gui/pxLogTextCtrl.cpp b/pcsx2/gui/pxLogTextCtrl.cpp
index 27d8037579..861e755742 100644
--- a/pcsx2/gui/pxLogTextCtrl.cpp
+++ b/pcsx2/gui/pxLogTextCtrl.cpp
@@ -85,7 +85,7 @@ void pxLogTextCtrl::OnResize( wxSizeEvent& evt )
int fonty;
GetTextExtent( L"blaH yeah", NULL, &fonty );
m_win32_LinesPerPage = (ctrly / fonty) + 1;
- m_win32_LinesPerScroll = m_win32_LinesPerPage * 0.72;
+ m_win32_LinesPerScroll = m_win32_LinesPerPage * 0.25;
#endif
evt.Skip();
diff --git a/pcsx2/x86/iVU0micro.cpp b/pcsx2/x86/iVU0micro.cpp
index 069a56e62c..72f14b9d14 100644
--- a/pcsx2/x86/iVU0micro.cpp
+++ b/pcsx2/x86/iVU0micro.cpp
@@ -55,8 +55,10 @@ using namespace VU0micro;
const VUmicroCpu recVU0 =
{
- recReset
- , recStep
- , recExecuteBlock
- , recClear
+ recReset
+, recStep
+, recExecuteBlock
+, recClear
+
+, false
};
diff --git a/pcsx2/x86/iVU1micro.cpp b/pcsx2/x86/iVU1micro.cpp
index 2f77aae004..7f3ada40e3 100644
--- a/pcsx2/x86/iVU1micro.cpp
+++ b/pcsx2/x86/iVU1micro.cpp
@@ -297,4 +297,6 @@ const VUmicroCpu recVU1 =
, recStep
, recExecuteBlock
, recClear
+
+, false
};