util: purge fixed-point library

This commit is contained in:
kojin 2021-08-30 03:10:48 -04:00 committed by Kojin
parent bda80fc748
commit 38f1a9a762
22 changed files with 162 additions and 566 deletions

View File

@ -18,7 +18,7 @@
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="PropertySheets">
<Import Project="..\..\vsprops\CommonLibrary.props" />
<Import Project="..\..\vsprops\3rdpartyDeps.props"/>
<Import Project="..\..\vsprops\3rdpartyDeps.props" />
<Import Project="..\..\vsprops\pthreads.props" />
<Import Condition="$(Configuration.Contains(Debug))" Project="..\..\vsprops\CodeGen_Debug.props" />
<Import Condition="$(Configuration.Contains(Devel))" Project="..\..\vsprops\CodeGen_Devel.props" />
@ -96,7 +96,6 @@
<ClInclude Include="..\..\include\Utilities\Dependencies.h" />
<ClInclude Include="..\..\include\Utilities\EventSource.h" />
<ClInclude Include="..\..\include\Utilities\Exceptions.h" />
<ClInclude Include="..\..\include\Utilities\FixedPointTypes.h" />
<ClInclude Include="..\..\include\Utilities\General.h" />
<ClInclude Include="..\..\include\Utilities\MathUtils.h" />
<ClInclude Include="..\..\include\Utilities\MemcpyFast.h" />

View File

@ -150,9 +150,6 @@
<ClInclude Include="..\..\include\Utilities\Exceptions.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Utilities\FixedPointTypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Utilities\General.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -214,4 +211,4 @@
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
</Project>

View File

@ -1,75 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "Dependencies.h"
template <int Precision>
struct FixedInt
{
s32 Raw;
FixedInt();
FixedInt(int signedval);
FixedInt(double doubval);
FixedInt(float floval);
bool operator==(const FixedInt<Precision> &right) const { return Raw == right.Raw; }
bool operator!=(const FixedInt<Precision> &right) const { return Raw != right.Raw; }
bool operator>(const FixedInt<Precision> &right) const { return Raw > right.Raw; };
bool operator>=(const FixedInt<Precision> &right) const { return Raw >= right.Raw; };
bool operator<(const FixedInt<Precision> &right) const { return Raw < right.Raw; };
bool operator<=(const FixedInt<Precision> &right) const { return Raw <= right.Raw; };
FixedInt<Precision> operator+(const FixedInt<Precision> &right) const;
FixedInt<Precision> operator-(const FixedInt<Precision> &right) const;
FixedInt<Precision> &operator+=(const FixedInt<Precision> &right);
FixedInt<Precision> &operator-=(const FixedInt<Precision> &right);
FixedInt<Precision> &ConfineTo(const FixedInt<Precision> &low, const FixedInt<Precision> &high);
FixedInt<Precision> operator*(const FixedInt<Precision> &right) const;
FixedInt<Precision> operator/(const FixedInt<Precision> &right) const;
FixedInt<Precision> &operator*=(const FixedInt<Precision> &right);
FixedInt<Precision> &operator/=(const FixedInt<Precision> &right);
static bool OverflowCheck(int signedval);
static bool OverflowCheck(double signedval);
int GetWhole() const;
int GetFraction() const;
FixedInt<Precision> &SetRaw(s32 rawsrc);
FixedInt<Precision> &Round();
FixedInt<Precision> &SetWhole(s32 wholepart);
FixedInt<Precision> &SetFraction(u32 fracpart);
wxString ToString() const;
wxString ToString(int fracDigits) const;
double ToDouble() const;
float ToFloat() const;
int ToIntTruncated() const;
int ToIntRounded() const;
static bool TryFromString(FixedInt<Precision> &dest, const wxString &parseFrom);
static FixedInt<Precision> FromString(const wxString &parseFrom, const FixedInt<Precision> &defval);
static FixedInt<Precision> FromString(const wxString parseFrom);
};
typedef FixedInt<256> Fixed256;
typedef FixedInt<100> Fixed100;

View File

@ -1,252 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "FixedPointTypes.h"
#include <cmath> // for pow!
template <int Precision>
FixedInt<Precision>::FixedInt()
{
Raw = 0;
}
template <int Precision>
FixedInt<Precision>::FixedInt(int signedval)
{
Raw = signedval * Precision;
}
template <int Precision>
FixedInt<Precision>::FixedInt(double doubval)
{
Raw = lround(doubval * (double)Precision);
}
template <int Precision>
FixedInt<Precision>::FixedInt(float floval)
{
Raw = lroundf(floval * (float)Precision);
}
template <int Precision>
FixedInt<Precision> FixedInt<Precision>::operator+(const FixedInt<Precision> &right) const
{
return FixedInt<Precision>().SetRaw(Raw + right.Raw);
}
template <int Precision>
FixedInt<Precision> FixedInt<Precision>::operator-(const FixedInt<Precision> &right) const
{
return FixedInt<Precision>().SetRaw(Raw - right.Raw);
}
template <int Precision>
FixedInt<Precision> &FixedInt<Precision>::operator+=(const FixedInt<Precision> &right)
{
return SetRaw(Raw + right.Raw);
}
template <int Precision>
FixedInt<Precision> &FixedInt<Precision>::operator-=(const FixedInt<Precision> &right)
{
return SetRaw(Raw - right.Raw);
}
template <int Precision>
FixedInt<Precision> &FixedInt<Precision>::ConfineTo(const FixedInt<Precision> &low, const FixedInt<Precision> &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.
template <int Precision>
FixedInt<Precision> FixedInt<Precision>::operator*(const FixedInt<Precision> &right) const
{
s64 mulres = (s64)Raw * right.Raw;
return FixedInt<Precision>().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.
template <int Precision>
FixedInt<Precision> FixedInt<Precision>::operator/(const FixedInt<Precision> &right) const
{
s64 divres = Raw * Precision;
return FixedInt<Precision>().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.
template <int Precision>
FixedInt<Precision> &FixedInt<Precision>::operator*=(const FixedInt<Precision> &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.
template <int Precision>
FixedInt<Precision> &FixedInt<Precision>::operator/=(const FixedInt<Precision> &right)
{
s64 divres = Raw * Precision;
return SetRaw((s32)(divres / right.Raw));
}
// returns TRUE if the value overflows the legal integer range of this container.
template <int Precision>
bool FixedInt<Precision>::OverflowCheck(int signedval)
{
return (signedval >= (INT_MAX / Precision));
}
// returns TRUE if the value overflows the legal integer range of this container.
template <int Precision>
bool FixedInt<Precision>::OverflowCheck(double signedval)
{
return (signedval >= (INT_MAX / Precision));
}
template <int Precision>
int FixedInt<Precision>::GetWhole() const
{
return Raw / Precision;
}
template <int Precision>
int FixedInt<Precision>::GetFraction() const
{
return Raw % Precision;
}
template <int Precision>
FixedInt<Precision> &FixedInt<Precision>::SetRaw(s32 rawsrc)
{
Raw = rawsrc;
return *this;
}
template <int Precision>
FixedInt<Precision> &FixedInt<Precision>::Round()
{
Raw = ToIntRounded();
return *this;
}
template <int Precision>
FixedInt<Precision> &FixedInt<Precision>::SetWhole(s32 wholepart)
{
pxAssert(wholepart < (INT_MAX / Precision));
Raw = GetFraction() + (wholepart * Precision);
return *this;
}
template <int Precision>
FixedInt<Precision> &FixedInt<Precision>::SetFraction(u32 fracpart)
{
Raw = (GetWhole() * Precision) + fracpart;
return *this;
}
template <int Precision>
wxString FixedInt<Precision>::ToString() const
{
return wxsFormat(L"%d.%02d", GetWhole(), (GetFraction() * 100) / Precision);
}
template <int Precision>
wxString FixedInt<Precision>::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);
wxString fmt = wxsFormat(L"%%d.%%0%dd", fracDigits);
return wxsFormat(fmt, GetWhole(), (GetFraction() * mulby) / Precision);
}
template <int Precision>
double FixedInt<Precision>::ToDouble() const
{
return ((double)Raw / (double)Precision);
}
template <int Precision>
float FixedInt<Precision>::ToFloat() const
{
return ((float)Raw / (float)Precision);
}
template <int Precision>
int FixedInt<Precision>::ToIntTruncated() const
{
return Raw / Precision;
}
template <int Precision>
int FixedInt<Precision>::ToIntRounded() const
{
return (Raw + (Precision / 2)) / Precision;
}
template <int Precision>
bool FixedInt<Precision>::TryFromString(FixedInt<Precision> &dest, const wxString &parseFrom)
{
long whole = 0, frac = 0;
const wxString beforeFirst(parseFrom.BeforeFirst(L'.'));
const wxString afterFirst(parseFrom.AfterFirst(L'.').Mid(0, 5));
bool success = true;
if (!beforeFirst.IsEmpty())
success = success && beforeFirst.ToLong(&whole);
if (!afterFirst.IsEmpty())
success = success && afterFirst.ToLong(&frac);
if (!success)
return false;
dest.SetWhole(whole);
if (afterFirst.Length() != 0 && frac != 0) {
int fracPower = (int)pow(10.0, (int)afterFirst.Length());
dest.SetFraction((frac * Precision) / fracPower);
}
return true;
}
template <int Precision>
FixedInt<Precision> FixedInt<Precision>::FromString(const wxString &parseFrom, const FixedInt<Precision> &defval)
{
FixedInt<Precision> dest;
if (!TryFromString(dest, parseFrom))
return defval;
return dest;
}
// This version of FromString throws a ParseError exception if the conversion fails.
template <int Precision>
FixedInt<Precision> FixedInt<Precision>::FromString(const wxString parseFrom)
{
FixedInt<Precision> dest;
if (!TryFromString(dest, parseFrom))
throw Exception::ParseError()
.SetDiagMsg(wxsFormat(L"Parse error on FixedInt<%d>::FromString", Precision));
return dest;
}

View File

@ -16,7 +16,6 @@
#pragma once
#include "Path.h"
#include "FixedPointTypes.h"
#include <wx/config.h>
#include <wx/gdicmn.h>
@ -64,7 +63,7 @@ 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, double& value, const double defvalue = 0.0) = 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;
@ -127,7 +126,7 @@ 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, double& value, const double defvalue = 0.0) override;
void Entry(const wxString &var, wxPoint &value, const wxPoint defvalue = wxDefaultPosition);
void Entry(const wxString &var, wxSize &value, const wxSize defvalue = wxDefaultSize);
@ -165,7 +164,7 @@ 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, double &value, const double defvalue = 0.0) override;
void Entry(const wxString &var, wxPoint &value, const wxPoint defvalue = wxDefaultPosition);
void Entry(const wxString &var, wxSize &value, const wxSize defvalue = wxDefaultSize);

View File

@ -10,7 +10,6 @@ add_library(Utilities)
# Utilities sources
target_sources(Utilities PRIVATE
VirtualMemory.cpp
../../include/Utilities/FixedPointTypes.inl
../../include/Utilities/EventSource.inl
../../include/Utilities/SafeArray.inl
CheckedStaticBox.cpp
@ -47,7 +46,6 @@ target_sources(Utilities PRIVATE
../../include/Utilities/Dependencies.h
../../include/Utilities/EventSource.h
../../include/Utilities/Exceptions.h
../../include/Utilities/FixedPointTypes.h
../../include/Utilities/General.h
../../include/Utilities/MemcpyFast.h
../../include/Utilities/MemsetFast.inl

View File

@ -20,12 +20,6 @@
const wxRect wxDefaultRect(wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, wxDefaultCoord);
// Implement FixedPointTypes (for lack of a better location, for now)
#include "FixedPointTypes.inl"
template struct FixedInt<100>;
template struct FixedInt<256>;
wxDirName g_fullBaseDirName = wxDirName(L"");
void SetFullBaseDir(wxDirName appRoot)
{
@ -196,15 +190,15 @@ int IniLoader::EntryBitfield(const wxString &var, int value, const int defvalue)
return result;
}
void IniLoader::Entry(const wxString &var, Fixed100 &value, const Fixed100 defvalue)
void IniLoader::Entry(const wxString &var, double& value, const double 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.. >_<
auto readval = wxString::FromDouble(value);
wxString readval(value.ToString());
if (m_Config)
m_Config->Read(var, &readval);
value = Fixed100::FromString(readval, value);
if (!readval.ToDouble(&value))
value = 0.0;
}
void IniLoader::Entry(const wxString &var, wxPoint &value, const wxPoint defvalue)
@ -361,15 +355,12 @@ int IniSaver::EntryBitfield(const wxString &var, int value, const int defvalue)
return value;
}
void IniSaver::Entry(const wxString &var, Fixed100 &value, const Fixed100 defvalue)
void IniSaver::Entry(const wxString &var, double &value, const double defvalue)
{
if (!m_Config)
return;
// 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());
m_Config->Write(var, wxString::FromDouble(value));
}
void IniSaver::Entry(const wxString &var, wxPoint &value, const wxPoint defvalue)

View File

@ -1058,7 +1058,7 @@ u8 monthmap[13] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void cdvdVsync()
{
cdvd.RTCcount++;
if (cdvd.RTCcount < (GetVerticalFrequency().ToIntRounded()))
if (cdvd.RTCcount < GetVerticalFrequency())
return;
cdvd.RTCcount = 0;

View File

@ -16,8 +16,6 @@
#pragma once
#include "x86emitter/tools.h"
#include "Utilities/FixedPointTypes.h"
#include "Utilities/General.h"
#include <wx/filename.h>
@ -282,24 +280,23 @@ struct Pcsx2Config
// ------------------------------------------------------------------------
struct GSOptions
{
int VsyncQueueSize{ 2 };
// forces the MTGS to execute tags/tasks in fully blocking/synchronous
// style. Useful for debugging potential bugs in the MTGS pipeline.
bool SynchronousMTGS;
// style. Useful for debugging potential bugs in the MTGS pipeline.
bool SynchronousMTGS{ false };
bool FrameLimitEnable{ true };
bool FrameSkipEnable{ false };
int VsyncQueueSize;
VsyncMode VsyncEnable{ VsyncMode::Off };
bool FrameLimitEnable;
bool FrameSkipEnable;
VsyncMode VsyncEnable;
int FramesToDraw{ 2 }; // number of consecutive frames (fields) to render
int FramesToSkip{ 2 }; // number of consecutive frames (fields) to skip
int FramesToDraw; // number of consecutive frames (fields) to render
int FramesToSkip; // number of consecutive frames (fields) to skip
double LimitScalar{ 1.0 };
double FramerateNTSC{ 59.94 };
double FrameratePAL{ 50.00 };
Fixed100 LimitScalar;
Fixed100 FramerateNTSC;
Fixed100 FrameratePAL;
GSOptions();
void LoadSave( IniInterface& conf );
int GetVsync() const;

View File

@ -183,28 +183,28 @@ static u64 m_iStart=0;
struct vSyncTimingInfo
{
Fixed100 Framerate; // frames per second (8 bit fixed)
double Framerate; // frames per second (8 bit fixed)
GS_VideoMode VideoMode; // used to detect change (interlaced/progressive)
u32 Render; // time from vblank end to vblank start (cycles)
u32 Blank; // time from vblank start to vblank end (cycles)
u32 Render; // time from vblank end to vblank start (cycles)
u32 Blank; // time from vblank start to vblank end (cycles)
u32 GSBlank; // GS CSR is swapped roughly 3.5 hblank's after vblank start
u32 GSBlank; // GS CSR is swapped roughly 3.5 hblank's after vblank start
u32 hSyncError; // rounding error after the duration of a rendered frame (cycles)
u32 hRender; // time from hblank end to hblank start (cycles)
u32 hBlank; // time from hblank start to hblank end (cycles)
u32 hScanlinesPerFrame; // number of scanlines per frame (525/625 for NTSC/PAL)
u32 hSyncError; // rounding error after the duration of a rendered frame (cycles)
u32 hRender; // time from hblank end to hblank start (cycles)
u32 hBlank; // time from hblank start to hblank end (cycles)
u32 hScanlinesPerFrame; // number of scanlines per frame (525/625 for NTSC/PAL)
};
static vSyncTimingInfo vSyncInfo;
static void vSyncInfoCalc(vSyncTimingInfo* info, Fixed100 framesPerSecond, u32 scansPerFrame)
static void vSyncInfoCalc(vSyncTimingInfo* info, double framesPerSecond, u32 scansPerFrame)
{
// I use fixed point math here to have strict control over rounding errors. --air
constexpr double clock = static_cast<double>(PS2CLK);
u64 Frame = ((u64)PS2CLK * 1000000ULL) / (framesPerSecond * 100).ToIntRounded();
const u64 Frame = clock * 10000ULL / framesPerSecond;
const u64 Scanline = Frame / scansPerFrame;
// There are two renders and blanks per frame. This matches the PS2 test results.
@ -281,7 +281,7 @@ const char* ReportVideoMode()
}
}
Fixed100 GetVerticalFrequency()
double GetVerticalFrequency()
{
// Note about NTSC/PAL "double strike" modes:
// NTSC and PAL can be configured in such a way to produce a non-interlaced signal.
@ -307,7 +307,7 @@ Fixed100 GetVerticalFrequency()
switch (gsVideoMode)
{
case GS_VideoMode::Uninitialized: // SetGsCrt hasn't executed yet, give some temporary values.
return 60;
return 60.00;
case GS_VideoMode::PAL:
case GS_VideoMode::DVD_PAL:
return gsIsInterlaced ? EmuConfig.GS.FrameratePAL : EmuConfig.GS.FrameratePAL - 0.24f;
@ -321,7 +321,7 @@ Fixed100 GetVerticalFrequency()
case GS_VideoMode::HDTV_720P:
case GS_VideoMode::SDTV_576P:
case GS_VideoMode::VESA:
return 60;
return 60.00;
default:
// Pass NTSC vertical frequency value when unknown video mode is detected.
return FRAMERATE_NTSC * 2;
@ -336,83 +336,75 @@ u32 UpdateVSyncRate()
// the GS's output circuit. It is the same regardless if the GS is outputting interlace
// or progressive scan content.
Fixed100 framerate = GetVerticalFrequency() / 2;
u32 scanlines = 0;
bool isCustom = false;
const double vertical_frequency = GetVerticalFrequency();
const double frames_per_second = vertical_frequency / 2.0;
const double frame_limit = frames_per_second * EmuConfig.GS.LimitScalar;
const double tick_rate = GetTickFrequency() / 2.0;
const s64 ticks = static_cast<s64>(tick_rate / std::max(frame_limit, 1.0));
u32 total_scanlines = 0;
bool custom = false;
//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.
scanlines = SCANLINES_TOTAL_NTSC;
total_scanlines = SCANLINES_TOTAL_NTSC;
break;
case GS_VideoMode::PAL:
case GS_VideoMode::DVD_PAL:
isCustom = (EmuConfig.GS.FrameratePAL != 50.0);
scanlines = SCANLINES_TOTAL_PAL;
custom = (EmuConfig.GS.FrameratePAL != 50.0);
total_scanlines = SCANLINES_TOTAL_PAL;
break;
case GS_VideoMode::NTSC:
case GS_VideoMode::DVD_NTSC:
isCustom = (EmuConfig.GS.FramerateNTSC != 59.94);
scanlines = SCANLINES_TOTAL_NTSC;
custom = (EmuConfig.GS.FramerateNTSC != 59.94);
total_scanlines = SCANLINES_TOTAL_NTSC;
break;
case GS_VideoMode::SDTV_480P:
case GS_VideoMode::SDTV_576P:
case GS_VideoMode::HDTV_720P:
case GS_VideoMode::VESA:
scanlines = SCANLINES_TOTAL_NTSC;
total_scanlines = SCANLINES_TOTAL_NTSC;
break;
case GS_VideoMode::HDTV_1080P:
case GS_VideoMode::HDTV_1080I:
scanlines = SCANLINES_TOTAL_1080;
total_scanlines = SCANLINES_TOTAL_1080;
break;
case GS_VideoMode::Unknown:
default:
// Falls through to default when unidentified mode parameter of SetGsCrt is detected.
// For Release builds, keep using the NTSC timing values when unknown video mode is detected.
// Assert will be triggered for debug/dev builds.
scanlines = SCANLINES_TOTAL_NTSC;
total_scanlines = SCANLINES_TOTAL_NTSC;
Console.Error("PCSX2-Counters: Unknown video mode detected");
pxAssertDev(false , "Unknown video mode detected via SetGsCrt");
}
bool ActiveVideoMode = gsVideoMode != GS_VideoMode::Uninitialized;
if (vSyncInfo.Framerate != framerate || vSyncInfo.VideoMode != gsVideoMode)
const bool video_mode_initialized = gsVideoMode != GS_VideoMode::Uninitialized;
if (vSyncInfo.Framerate != frames_per_second || vSyncInfo.VideoMode != gsVideoMode)
{
vSyncInfo.VideoMode = gsVideoMode;
vSyncInfoCalc( &vSyncInfo, framerate, scanlines );
if(ActiveVideoMode)
Console.WriteLn( Color_Green, "(UpdateVSyncRate) Mode Changed to %s.", ReportVideoMode());
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
vsyncCounter.CycleT = vSyncInfo.Render; // Amount of cycles before the counter will be updated
vSyncInfoCalc(&vSyncInfo, frames_per_second, total_scanlines);
if (video_mode_initialized)
Console.WriteLn(Color_Green, "(UpdateVSyncRate) Mode Changed to %s.", ReportVideoMode());
if (custom && video_mode_initialized)
Console.Indent().WriteLn(Color_StrongGreen, "... with user configured refresh rate: %.02f Hz", vertical_frequency);
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();
}
Fixed100 fpslimit = framerate *
( pxAssert( EmuConfig.GS.LimitScalar > 0 ) ? EmuConfig.GS.LimitScalar : 1.0 );
//s64 debugme = GetTickFrequency() / 3000;
s64 ticks = (GetTickFrequency()*500) / (fpslimit * 1000).ToIntRounded();
if( m_iTicks != ticks )
{
if (m_iTicks != ticks)
m_iTicks = ticks;
gsOnModeChanged( vSyncInfo.Framerate, m_iTicks );
if (ActiveVideoMode)
Console.WriteLn( Color_Green, "(UpdateVSyncRate) FPS Limit Changed : %.02f fps", fpslimit.ToFloat()*2 );
}
m_iStart = GetCPUTicks();
return (u32)m_iTicks;
return static_cast<u32>(m_iTicks);
}
void frameLimitReset()
@ -439,9 +431,9 @@ static __fi void frameLimit()
return;
}
u64 uExpectedEnd = m_iStart + m_iTicks; // Compute when we would expect this frame to end, assuming everything goes perfectly perfect.
u64 iEnd = GetCPUTicks(); // The current tick we actually stopped on.
s64 sDeltaTime = iEnd - uExpectedEnd; // The diff between when we stopped and when we expected to.
const u64 uExpectedEnd = m_iStart + m_iTicks; // Compute when we would expect this frame to end, assuming everything goes perfectly perfect.
const u64 iEnd = GetCPUTicks(); // The current tick we actually stopped on.
const s64 sDeltaTime = iEnd - uExpectedEnd; // The diff between when we stopped and when we expected to.
// If frame ran too long...
if (sDeltaTime >= m_iTicks)

View File

@ -28,19 +28,12 @@ using namespace R5900;
__aligned16 u8 g_RealGSMem[Ps2MemSize::GSregs];
void gsOnModeChanged( Fixed100 framerate, u32 newTickrate )
{
GetMTGS().SendSimplePacket( GS_RINGTYPE_MODECHANGE, framerate.Raw, newTickrate, 0 );
}
void gsSetVideoMode(GS_VideoMode mode )
void gsSetVideoMode(GS_VideoMode mode)
{
gsVideoMode = mode;
UpdateVSyncRate();
}
// Make sure framelimiter options are in sync with GS capabilities.
void gsReset()
{
@ -58,13 +51,13 @@ void gsUpdateFrequency(Pcsx2Config& config)
switch (g_LimiterMode)
{
case LimiterModeType::Limit_Nominal:
config.GS.LimitScalar = g_Conf->Framerate.NominalScalar;
config.GS.LimitScalar = g_Conf->Framerate.NominalScalar / 100.0;
break;
case LimiterModeType::Limit_Slomo:
config.GS.LimitScalar = g_Conf->Framerate.SlomoScalar;
config.GS.LimitScalar = g_Conf->Framerate.SlomoScalar / 100.0;
break;
case LimiterModeType::Limit_Turbo:
config.GS.LimitScalar = g_Conf->Framerate.TurboScalar;
config.GS.LimitScalar = g_Conf->Framerate.TurboScalar / 100.0;
break;
default:
pxAssert("Unknown framelimiter mode!");

View File

@ -20,7 +20,7 @@
#include "Gif.h"
#include "GS/GS.h"
extern Fixed100 GetVerticalFrequency();
extern double GetVerticalFrequency();
extern __aligned16 u8 g_RealGSMem[Ps2MemSize::GSregs];
enum CSR_FifoState
@ -282,20 +282,19 @@ extern bool gsIsInterlaced;
enum MTGS_RingCommand
{
GS_RINGTYPE_P1
, GS_RINGTYPE_P2
, GS_RINGTYPE_P3
, GS_RINGTYPE_VSYNC
, GS_RINGTYPE_FRAMESKIP
, GS_RINGTYPE_FREEZE
, GS_RINGTYPE_RESET // issues a GSreset() command.
, GS_RINGTYPE_SOFTRESET // issues a soft reset for the GIF
, GS_RINGTYPE_MODECHANGE // for issued mode changes.
, GS_RINGTYPE_CRC
, GS_RINGTYPE_GSPACKET
, GS_RINGTYPE_MTVU_GSPACKET
, GS_RINGTYPE_INIT_READ_FIFO1
, GS_RINGTYPE_INIT_READ_FIFO2
GS_RINGTYPE_P1,
GS_RINGTYPE_P2,
GS_RINGTYPE_P3,
GS_RINGTYPE_VSYNC,
GS_RINGTYPE_FRAMESKIP,
GS_RINGTYPE_FREEZE,
GS_RINGTYPE_RESET, // issues a GSreset() command.
GS_RINGTYPE_SOFTRESET, // issues a soft reset for the GIF
GS_RINGTYPE_CRC,
GS_RINGTYPE_GSPACKET,
GS_RINGTYPE_MTVU_GSPACKET,
GS_RINGTYPE_INIT_READ_FIFO1,
GS_RINGTYPE_INIT_READ_FIFO2,
};
@ -410,12 +409,11 @@ extern SysMtgsThread& GetMTGS();
extern s32 gsOpen();
extern void gsClose();
extern void gsReset();
extern void gsOnModeChanged( Fixed100 framerate, u32 newTickrate );
extern void gsSetVideoMode( GS_VideoMode mode );
extern void gsSetVideoMode(GS_VideoMode mode);
extern void gsResetFrameSkip();
extern void gsPostVsyncStart();
extern void gsFrameSkip();
extern void gsUpdateFrequency( Pcsx2Config& config );
extern void gsUpdateFrequency(Pcsx2Config& config);
// Some functions shared by both the GS and MTGS
extern void _gs_ResetFrameskip();

View File

@ -343,12 +343,12 @@ GSVector4i GSRenderer::ComputeDrawRectangle(int width, int height) const
else if (arr > 1)
target_height = std::floor(f_height / arr + 0.5);
float zoom = g_Conf->GSWindow.Zoom.ToFloat() / 100.0;
float zoom = g_Conf->GSWindow.Zoom / 100.0;
if (zoom == 0) //auto zoom in untill black-bars are gone (while keeping the aspect ratio).
zoom = std::max((float)arr, (float)(1.0 / arr));
target_width *= zoom;
target_height *= zoom * g_Conf->GSWindow.StretchY.ToFloat() / 100.0;
target_height *= zoom * g_Conf->GSWindow.StretchY / 100.0;
double target_x, target_y;
if (target_width > f_width)
@ -361,8 +361,8 @@ GSVector4i GSRenderer::ComputeDrawRectangle(int width, int height) const
target_y = (f_height - target_height) * 0.5;
const double unit = .01 * std::min(target_x, target_y);
target_x += unit * g_Conf->GSWindow.OffsetX.ToFloat();
target_y += unit * g_Conf->GSWindow.OffsetY.ToFloat();
target_x += unit * g_Conf->GSWindow.OffsetX;
target_y += unit * g_Conf->GSWindow.OffsetY;
return GSVector4i(
static_cast<int>(std::floor(target_x)),

View File

@ -518,10 +518,6 @@ void SysMtgsThread::ExecuteTaskInThread()
}
break;
case GS_RINGTYPE_MODECHANGE:
// [TODO] some frameskip sync logic might be needed here!
break;
case GS_RINGTYPE_CRC:
GSsetGameCRC(tag.data[0], 0);
break;

View File

@ -217,24 +217,6 @@ void Pcsx2Config::CpuOptions::LoadSave( IniInterface& ini )
Recompiler.LoadSave( ini );
}
// Default GSOptions
Pcsx2Config::GSOptions::GSOptions()
{
FrameLimitEnable = true;
FrameSkipEnable = false;
VsyncEnable = VsyncMode::Off;
SynchronousMTGS = false;
VsyncQueueSize = 2;
FramesToDraw = 2;
FramesToSkip = 2;
LimitScalar = 1.0;
FramerateNTSC = 59.94;
FrameratePAL = 50.0;
}
void Pcsx2Config::GSOptions::LoadSave( IniInterface& ini )
{
ScopedIniGroup path( ini, L"GS" );

View File

@ -70,7 +70,6 @@
#include "Pcsx2Defs.h"
#include "i18n.h"
#include "Utilities/FixedPointTypes.h"
#include "Utilities/wxBaseTools.h"
#include "Utilities/Path.h"
#include "Utilities/Console.h"

View File

@ -24,6 +24,7 @@
#include <wx/stdpaths.h>
#include "DebugTools/Debug.h"
#include <memory>
#include <algorithm>
//////////////////////////////////////////////////////////////////////////////////////////
// PathDefs Namespace -- contains default values for various pcsx2 path names and locations.
@ -860,23 +861,13 @@ void AppConfig::InputRecordingOptions::loadSave(IniInterface& ini)
#endif
// ----------------------------------------------------------------------------
AppConfig::FramerateOptions::FramerateOptions()
{
NominalScalar = 1.0;
TurboScalar = 2.0;
SlomoScalar = 0.50;
SkipOnLimit = false;
SkipOnTurbo = false;
}
void AppConfig::FramerateOptions::SanityCheck()
{
// Ensure Conformation of various options...
NominalScalar .ConfineTo( 0.05, 10.0 );
TurboScalar .ConfineTo( 0.05, 10.0 );
SlomoScalar .ConfineTo( 0.05, 10.0 );
NominalScalar = std::clamp(NominalScalar, 5.0, 1000.0);
TurboScalar = std::clamp(TurboScalar, 5.0, 1000.0);
SlomoScalar = std::clamp(SlomoScalar, 5.0, 1000.0);
}
void AppConfig::FramerateOptions::LoadSave( IniInterface& ini )

View File

@ -206,28 +206,27 @@ public:
struct GSWindowOptions
{
// Closes the GS/Video port on escape (good for fullscreen activity)
bool CloseOnEsc;
bool DefaultToFullscreen;
bool AlwaysHideMouse;
bool DisableResizeBorders;
bool DisableScreenSaver;
bool CloseOnEsc;
bool DefaultToFullscreen;
bool AlwaysHideMouse;
bool DisableResizeBorders;
bool DisableScreenSaver;
AspectRatioType AspectRatio;
FMVAspectRatioSwitchType FMVAspectRatioSwitch;
Fixed100 Zoom;
Fixed100 StretchY;
Fixed100 OffsetX;
Fixed100 OffsetY;
double Zoom;
double StretchY;
double OffsetX;
double OffsetY;
wxSize WindowSize;
wxPoint WindowPos;
bool IsMaximized;
bool IsFullscreen;
bool EnableVsyncWindowFlag;
wxSize WindowSize;
wxPoint WindowPos;
bool IsToggleFullscreenOnDoubleClick;
bool IsMaximized;
bool IsFullscreen;
bool EnableVsyncWindowFlag;
bool IsToggleFullscreenOnDoubleClick;
GSWindowOptions();
@ -237,15 +236,13 @@ public:
struct FramerateOptions
{
bool SkipOnLimit;
bool SkipOnTurbo;
bool SkipOnLimit{ false };
bool SkipOnTurbo{ false };
Fixed100 NominalScalar;
Fixed100 TurboScalar;
Fixed100 SlomoScalar;
double NominalScalar{ 100.0 };
double TurboScalar{ 200.0 };
double SlomoScalar{ 50.0 };
FramerateOptions();
void LoadSave( IniInterface& conf );
void SanityCheck();
};

View File

@ -686,7 +686,7 @@ void GSFrame::OnUpdateTitle( wxTimerEvent& evt )
AppConfig::UiTemplateOptions& templates = g_Conf->Templates;
float percentage = (fps * 100) / GetVerticalFrequency().ToFloat();
const float percentage = (fps * 100) / GetVerticalFrequency();
char gsDest[128];
gsDest[0] = 0; // No need to set whole array to NULL.

View File

@ -211,22 +211,22 @@ namespace Implementations
void GSwindow_OffsetYplus()
{
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat(), g_Conf->GSWindow.OffsetY.ToFloat() + 1);
SetOffset(g_Conf->GSWindow.OffsetX, g_Conf->GSWindow.OffsetY + 1);
}
void GSwindow_OffsetYminus()
{
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat(), g_Conf->GSWindow.OffsetY.ToFloat() - 1);
SetOffset(g_Conf->GSWindow.OffsetX, g_Conf->GSWindow.OffsetY - 1);
}
void GSwindow_OffsetXplus()
{
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat() + 1, g_Conf->GSWindow.OffsetY.ToFloat());
SetOffset(g_Conf->GSWindow.OffsetX + 1, g_Conf->GSWindow.OffsetY);
}
void GSwindow_OffsetXminus()
{
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat() - 1, g_Conf->GSWindow.OffsetY.ToFloat());
SetOffset(g_Conf->GSWindow.OffsetX - 1, g_Conf->GSWindow.OffsetY);
}
void GSwindow_OffsetReset()
@ -244,11 +244,11 @@ namespace Implementations
void GSwindow_ZoomInY()
{
SetZoomY(g_Conf->GSWindow.StretchY.ToFloat() + 1);
SetZoomY(g_Conf->GSWindow.StretchY + 1);
}
void GSwindow_ZoomOutY()
{
SetZoomY(g_Conf->GSWindow.StretchY.ToFloat() - 1);
SetZoomY(g_Conf->GSWindow.StretchY - 1);
}
void GSwindow_ZoomResetY()
{
@ -270,7 +270,7 @@ namespace Implementations
void GSwindow_ZoomIn()
{
float z = g_Conf->GSWindow.Zoom.ToFloat();
float z = g_Conf->GSWindow.Zoom;
if (z == 0)
z = 100;
z++;
@ -278,7 +278,7 @@ namespace Implementations
}
void GSwindow_ZoomOut()
{
float z = g_Conf->GSWindow.Zoom.ToFloat();
float z = g_Conf->GSWindow.Zoom;
if (z == 0)
z = 100;
z--;
@ -286,7 +286,7 @@ namespace Implementations
}
void GSwindow_ZoomToggle()
{
float z = g_Conf->GSWindow.Zoom.ToFloat();
float z = g_Conf->GSWindow.Zoom;
if (z == 100)
z = 0;
else

View File

@ -162,7 +162,7 @@ void Panels::GSWindowSettingsPanel::ApplyConfigToGui(AppConfig& configToApply, i
m_combo_AspectRatio->SetSelection((int)conf.AspectRatio);
m_combo_FMVAspectRatioSwitch->SetSelection(enum_cast(conf.FMVAspectRatioSwitch));
m_text_Zoom->ChangeValue(conf.Zoom.ToString());
m_text_Zoom->ChangeValue(wxString::FromDouble(conf.Zoom, 2));
m_check_DclickFullscreen->SetValue(conf.IsToggleFullscreenOnDoubleClick);
@ -186,7 +186,10 @@ void Panels::GSWindowSettingsPanel::Apply()
appconf.AspectRatio = (AspectRatioType)m_combo_AspectRatio->GetSelection();
appconf.FMVAspectRatioSwitch = (FMVAspectRatioSwitchType)m_combo_FMVAspectRatioSwitch->GetSelection();
appconf.Zoom = Fixed100::FromString(m_text_Zoom->GetValue());
double new_zoom = 0.0;
if (m_text_Zoom->GetValue().ToDouble(&new_zoom))
appconf.Zoom = new_zoom;
gsconf.VsyncEnable = static_cast<VsyncMode>(m_combo_vsync->GetSelection());

View File

@ -113,29 +113,23 @@ void Panels::FramelimiterPanel::ApplyConfigToGui( AppConfig& configToApply, int
if( ! (flags & AppConfig::APPLY_FLAG_FROM_PRESET) ){ //Presets don't control these: only change if config doesn't come from preset.
m_check_LimiterDisable->SetValue( !gsconf.FrameLimitEnable );
m_check_LimiterDisable->SetValue(!gsconf.FrameLimitEnable);
m_spin_TurboPct ->SetValue( appfps.TurboScalar.Raw );
m_spin_SlomoPct ->SetValue( appfps.SlomoScalar.Raw );
m_spin_TurboPct->SetValue(appfps.TurboScalar);
m_spin_SlomoPct->SetValue(appfps.SlomoScalar);
m_spin_TurboPct ->Enable( 1 );
m_spin_SlomoPct ->Enable( 1 );
m_spin_TurboPct->Enable(true);
m_spin_SlomoPct->Enable(true);
}
m_text_BaseNtsc ->ChangeValue( gsconf.FramerateNTSC.ToString() );
m_text_BasePal ->ChangeValue( gsconf.FrameratePAL.ToString() );
m_text_BaseNtsc->ChangeValue(wxString::FromDouble(gsconf.FramerateNTSC, 2));
m_text_BasePal->ChangeValue(wxString::FromDouble(gsconf.FrameratePAL, 2));
m_spin_NominalPct ->SetValue( appfps.NominalScalar.Raw );
m_spin_NominalPct ->Enable(!configToApply.EnablePresets);
m_spin_NominalPct->SetValue(appfps.NominalScalar);
m_spin_NominalPct->Enable(!configToApply.EnablePresets);
// Vsync timing controls only on devel builds / via manual ini editing
#ifdef PCSX2_DEVBUILD
m_text_BaseNtsc ->Enable(!configToApply.EnablePresets);
m_text_BasePal ->Enable(!configToApply.EnablePresets);
#else
m_text_BaseNtsc ->Enable( 0 );
m_text_BasePal ->Enable( 0 );
#endif
m_text_BaseNtsc->Enable(!configToApply.EnablePresets);
m_text_BasePal->Enable(!configToApply.EnablePresets);
}
void Panels::FramelimiterPanel::Apply()
@ -145,23 +139,20 @@ void Panels::FramelimiterPanel::Apply()
gsconf.FrameLimitEnable = !m_check_LimiterDisable->GetValue();
appfps.NominalScalar.Raw = m_spin_NominalPct ->GetValue();
appfps.TurboScalar.Raw = m_spin_TurboPct ->GetValue();
appfps.SlomoScalar.Raw = m_spin_SlomoPct ->GetValue();
appfps.NominalScalar = m_spin_NominalPct->GetValue();
appfps.TurboScalar = m_spin_TurboPct->GetValue();
appfps.SlomoScalar = m_spin_SlomoPct->GetValue();
try {
gsconf.FramerateNTSC = Fixed100::FromString( m_text_BaseNtsc->GetValue() );
gsconf.FrameratePAL = Fixed100::FromString( m_text_BasePal->GetValue() );
}
catch( Exception::ParseError& )
{
throw Exception::CannotApplySettings( this )
.SetDiagMsg(pxsFmt(
L"Error while parsing either NTSC or PAL framerate settings.\n\tNTSC Input = %s\n\tPAL Input = %s",
WX_STR(m_text_BaseNtsc->GetValue()), WX_STR(m_text_BasePal->GetValue())
) )
.SetUserMsg(_t("Error while parsing either NTSC or PAL framerate settings. Settings must be valid floating point numerics."));
}
wxString ntsc_framerate_string = m_text_BaseNtsc->GetValue();
wxString pal_framerate_string = m_text_BasePal->GetValue();
double framerate = 0.0;
if (ntsc_framerate_string.ToDouble(&framerate))
gsconf.FramerateNTSC = framerate;
if (pal_framerate_string.ToDouble(&framerate))
gsconf.FrameratePAL = framerate;
appfps.SanityCheck();